Java
Java
Java
Java는 객체 지향 프로그래밍 언어로, 플랫폼 독립성을 제공하는 특징이 있음. Java 프로그램은 Java Virtual Machine(JVM)에서 실행되며, 다양한 운영 체제에서 동일한 코드를 실행할 수 있게 함.
Hello World
1
2
3
4
5
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
public class HelloWorld
:HelloWorld
라는 이름의 클래스를 정의함. Java에서는 모든 코드는 클래스 안에 있어야 함.public static void main(String[] args)
: Java 프로그램의 진입점인main
메서드를 정의함.public
은 접근 제어자,static
은 클래스 메서드임을 나타내며,void
는 반환값이 없음을 의미함.System.out.println("Hello, World!");
: 콘솔에 “Hello, World!”를 출력함.System.out
은 표준 출력 스트림을 나타내며,println
메서드는 문자열을 출력하고 줄바꿈을 함.- 파일 이름은 클래스 이름과 동일해야 하며, 확장자는
.java
임. 예를 들어, 위 코드는HelloWorld.java
로 저장되어야 함.
Java vs. C++
- Array
- Java의 배열은 동적으로 생성됨. 배열 초기화시 기본값(0, false 등)이 자동으로 할당됨.
- 선언:
1 2
int[] arr = new int[5]; // 크기가 5인 정수형 배열 생성 int[][] arr2D = new int[3][4]; // 3x4 크기의 2차원 배열 생성
1 2 3 4 5
int* arr = new int[5]; // C++에서 동적 배열 생성 int* arr2D = new int*[3]; // 2차원 배열을 위한 포인터 배열 생성 for (int i = 0; i < 3; ++i) { arr2D[i] = new int[4]; // 각 행에 대해 크기가 4인 배열 생성 }
- Java에서는 배열도 반환값으로 사용할 수 있음. C++에서는 배열을 반환할 수 없고, 포인터를 사용해야 함.
- Java에서는 배열의 크기에 대해 boundary check가 자동으로 수행됨. C++에서는 배열의 크기를 벗어나는 접근이 허용되며, 이는 런타임 오류를 발생시킬 수 있음.
- Java에서는 배열의 크기를
arr.length
로 확인할 수 있음. C++에서는sizeof(arr) / sizeof(arr[0])
를 사용하여 배열의 크기를 계산해야 함.
final
,const
- Java에서는
final
키워드를 사용하여 변수를 상수로 선언할 수 있음.final
로 선언된 변수는 초기화 후 값을 변경할 수 없음. - C++에서는
const
키워드를 사용하여 변수를 상수로 선언함.const
로 선언된 변수는 초기화 후 값을 변경할 수 없음. - 예시:
1
final int x = 10; // Java에서 상수 선언
1
const int x = 10; // C++에서 상수 선언
- Java에서는
static
- Java에서는
static
키워드가 지역 변수에 적용되지 않음.static
은 클래스 변수나 메서드에만 적용됨. - C++에서는
static
키워드를 사용하여 지역 변수를 정적 변수로 선언할 수 있음. 정적 변수는 함수 호출 간에 값을 유지함. - 예시:
1 2 3 4 5 6 7 8 9
class MyClass { static int count = 0; // 클래스 변수 static void increment() { count++; } } void func(){ static int localCount = 0; // Java에서는 지역 변수에 static을 사용할 수 없음, 컴파일 오류 발생 }
1 2 3 4
void myFunction() { static int count = 0; // 정적 지역 변수 count++; }
- Java에서는
- Casting
- Widening primitive conversion: 작은 타입에서 큰 타입으로 변환할 때는 자동으로 변환됨
예:int
->long
,float
->double
- Narrowing primitive conversion: 큰 타입에서 작은 타입으로 변환할 때는 명시적으로 캐스팅해야 함
예:long num = 123; int x = (int) num; // 명시적 캐스팅 필요
- Evaluation arithmetic order: 피연산자 중 하나라도 1.
double
, 2.float
, 3.long
타입이면 결과는 해당 타입으로 변환됨. 그 외의 경우는int
타입으로 유지됨. - Boolean 타입은 다른 타입으로 변환할 수 없음.
- Widening primitive conversion: 작은 타입에서 큰 타입으로 변환할 때는 자동으로 변환됨
Libraries
Java는 다양한 라이브러리를 제공하여 개발자가 쉽게 사용할 수 있도록 함. 대표적인 라이브러리로는 다음과 같은 것들이 있음:
- Java.lang: Java의 기본 클래스 라이브러리로, 문자열 처리, 수학 함수, 날짜 및 시간 등을 포함함.
- Java.lang.Math: 수학 관련 함수와 상수를 제공함.
Math.abs(x)
: 절댓값을 반환함.Math.max(a, b)
: 두 값 중 큰 값을 반환함.Math.min(a, b)
: 두 값 중 작은 값을 반환함.Math.sqrt(x)
: 제곱근을 반환함.Math.pow(x, y)
: x의 y제곱을 반환함.Math.random()
: 0.0 이상 1.0 미만의 난수를 반환함.Math.PI
: 원주율을 나타내는 상수.Math.E
: 자연상수 e를 나타내는 상수.
- Java.lang.String: 문자열을 처리하는 클래스.
String.length()
: 문자열의 길이를 반환함.String.charAt(index)
: 지정된 인덱스의 문자를 반환함.String.substring(start, end)
: 지정된 범위의 부분 문자열을 반환함.String.contains(substring)
: 문자열이 지정된 부분 문자열을 포함하는지 여부를 반환함.String.indexOf(substring)
: 지정된 부분 문자열의 첫 번째 인덱스를 반환함.String.toLowerCase()
,String.toUpperCase()
: 문자열을 소문자 또는 대문자로 변환함.String.trim()
: 문자열의 앞뒤 공백을 제거함.
- Java.lang.Math: 수학 관련 함수와 상수를 제공함.
Console I/O
Java에서는 콘솔 입출력을 위해 Java.lang.System
클래스를 사용함. System.out
은 표준 출력 스트림을 나타내며, System.in
은 표준 입력 스트림을 나타냄.
- 출력:
1 2 3
System.out.println("Hello, World!"); // 줄바꿈 포함 출력 System.out.print("Hello, World!"); // 줄바꿈 없이 출력 System.out.printf("Hello, %s!", "World"); // 형식화된 출력
Classes
- 멤버 변수는 field라고 불림
- 필드 값은 초기화시 기본값으로 초기화됨. 예를 들어,
int
타입은 0,boolean
타입은 false로 초기화됨.
- 필드 값은 초기화시 기본값으로 초기화됨. 예를 들어,
- 멤버 함수는 method라고 불림
- 선언 끝에
;
없음 - method는 선언된 자리에서 바로 정의되어야함
- Constructor: 클래스의 인스턴스를 생성할 때 호출되는 특별한 메서드. 클래스 이름과 동일하며, 반환 타입이 없음. 항상 new 키워드를 사용하여 객체를 생성함. 생성자가 명시적으로 정의되지 않으면, Java 컴파일러가 기본 생성자를 자동으로 추가함.
this
키워드로 생성자 안에 같은 클래스의 다른 생성자를 호출할 수 있음. - Access Modifiers: 클래스, 변수, 메서드의 접근 범위를 지정함.
public
: 모든 곳에서 접근 가능private
: 같은 클래스 내에서만 접근 가능protected
: 같은 클래스/패키지/서브클래스에서 접근 가능default
: 아무런 접근 제어자가 없을 때, 같은 패키지 내에서만 접근 가능- 대부분
public
아니면private
로 선언함.
null
: C++의nullptr
- destructor 없음
- 메서드 오버로딩 가능
- 연산자 오버로딩 불가능
Call by Value
Java에서는 모든 메서드 호출이 Call by Value로 이루어짐.
하지만 객체 참조가 포인터처럼 동작하기 때문에, 객체의 상태를 변경할 수 있음.
- 기본 타입(primitive type)은 값이 직접 전달됨. 메서드 내에서 값을 변경해도 원래 변수의 값은 변경되지 않음.
- 객체 파라미터가 새로운 객체를 가리키도록 수정 불가
- 객체 파라미터의 상태(필드 값)는 변경 가능
- C++의 const처럼 객체를 변경 못하도록 할 수 없음.
Packages
Java에서는 패키지를 사용하여 클래스를 그룹화하고, 네임스페이스를 제공함. 패키지는 클래스의 이름 충돌을 방지하고, 코드의 구조를 개선하는 데 도움을 줌.
- 패키지를 선언하려면 파일의 첫 줄에
package
키워드를 사용함.1 2 3 4
package com.example.myapp; // 패키지 선언, 폴더 구조와 일치해야 함 public class MyClass { // 클래스 내용 }
- 패키지에 속한 클래스를 사용하려면
import
키워드를 사용함.1 2
import com.example.myapp.MyClass; // 특정 클래스 가져오기 import com.example.myapp.*; // 패키지 내 모든 클래스 가져오기
import static
: 정적 멤버를 가져올 때 사용함. 예를 들어,Math
클래스의 정적 메서드를 사용할 때 유용함.1
import static java.lang.Math.*; // Math 클래스의 모든 정적 멤버 가져오기
Inheritance
- 상속을 사용하려면
extends
키워드를 사용함.1 2 3 4 5 6 7 8 9 10 11
public class Animal { public void makeSound() { System.out.println("Animal sound"); } } public class Dog extends Animal { @Override public void makeSound() { System.out.println("Bark"); } }
- super: 부모 클래스의 생성자를 호출할 때 사용함. 자식 클래스의 생성자에서
super()
를 호출하여 부모 클래스의 생성자를 명시적으로 호출할 수 있음.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public class Animal { public Animal(String name) { System.out.println("Animal constructor: " + name); } public void makeSound() { System.out.println("Animal sound"); } } public class Dog extends Animal { public Dog(String name) { super(name); // 부모 클래스의 생성자 호출 System.out.println("Dog constructor: " + name); } @Override public void makeSound() { super.makeSound(); // 부모 클래스의 메서드 호출 System.out.println("Bark"); } }
- 메서드에
final
키워드를 사용하면 해당 메서드를 오버라이드할 수 없음. 클래스에final
키워드를 사용하면 해당 클래스를 상속할 수 없음. Object
클래스: 모든 클래스의 최상위 클래스. 모든 클래스는Object
클래스를 암묵적으로 상속받음.Object
클래스에는toString()
,equals()
,hashCode()
등의 메서드가 정의되어 있음.- Polymorphism: 다형성은 동일한 메서드 이름이지만, 서로 다른 클래스에서 다른 동작을 수행하는 것을 의미함. Java에서는 메서드 오버로딩과 메서드 오버라이딩을 통해 다형성을 구현함.
- 메서드 오버로딩: 같은 이름의 메서드를 여러 개 정의할 수 있음. 매개변수의 타입이나 개수가 다르면 서로 다른 메서드로 인식됨.
- 메서드 오버라이딩: 부모 클래스의 메서드를 자식 클래스에서 재정의하여 사용할 수 있음.
@Override
어노테이션을 사용하여 명시적으로 표시할 수 있음. - Dynamic Binding: 런타임에 메서드 호출이 결정되는 것을 의미함. 자식 클래스의 메서드가 부모 클래스의 참조 변수로 호출될 때, 실제 객체의 타입에 따라 호출되는 메서드가 결정됨.
해당 포스트는 서울대학교 전기정보공학부 정교민 교수님의 프로그래밍방법론 25-1학기 강의를 정리한 내용입니다.
This post is licensed under CC BY 4.0 by the author.