멤버 변수는 초기화를 별도로 하지 않아도 선언 즉시 자신의 타입에 맞는 기본값으로 초기화됨.
그러나 지역변수는 반드시 초기화를 해줘야함.
class InitVar {
int x;
int y = x; // (O) 인스턴스 변수 x는 선언만 되어있어도 기본값인 0을 가지므로 사용 가능
void method() {
int a;
int b = a; // (X) 지역 변수 a를 초기화하지 않고 사용하여 에러 발생
}
}
멤버 변수를 초기화 하는데에는 크게 3가지 방법이 있음.
명시적 초기화
초기화 블럭
클래스 초기화 블럭
인스턴스 초기화 블럭
생성자
변수를 선언함과 동시에 초기화 하는것.
class Laptop {
int screenSize = 15; // 기본형 타입의 변수 초기화
Port[] p = new Port[4]; // 참조형 타입의 변수 초기화
...
}
초기화 블럭 내에서는 조건문, 반복문, 예외처리구문 등 자유롭게 사용 가능
멤버 변수로 배열을 다루는 케이스와 같이 처리할 양이 많거나 초기화 과정에서 예외처리가 필요할 때는 명시적 초기화 대신 초기화 블럭 안에서 작업을 수행하는 것이 효율적.
클래스 초기화 블럭과 인스턴스 초기화 블럭 2가지 종류가 있음.
class InitBlock {
static {
// 클래스 초기화 블럭
}
{
// 인스턴스 초기화 블럭
}
}
클래스 변수의 복잡한 초기화에 사용
클래스 내부에서 static {}
안에 변수들을 넣음
클래스가 메모리에 처음 load 될 때 한번만 수행
인스턴스 변수의 복잡한 초기화에 사용
클래스 내부에서 {}
안에 변수들을 넣음
인스턴스가 생성될 때마다 수행 (생성자보다도 먼저 수행됨)
모든 생성자에서 공통으로 수행되어야 하는 코드를 넣는데에 사용
코드의 중복을 줄여주어 오류 발생 가능성도 줄어듬
테스트 해보기
class InitBlock {
static {
System.out.println("클래스 초기화 블럭 실행");
}
{
System.out.println("인스턴스 초기화 블럭 실행");
}
InitBlock() {
System.out.println("생성자 실행");
}
public static void main(String[] args) {
System.out.println("첫번째 인스턴스 b1 생성");
InitBlock b1 = new InitBlock();
System.out.println("두번째 인스턴스 b2 생성");
InitBlock b2 = new InitBlock();
}
}
실행 결과:
클래스 초기화 블럭 실행
첫번째 인스턴스 b1 생성
인스턴스 초기화 블럭 실행
생성자 실행
두번째 인스턴스 b2 생성
인스턴스 초기화 블럭 실행
생성자 실행
종류 | 초기화 시점 | 초기화 순서 |
클래스 변수 | 클래스가 처음 load될 때, 딱 한번 | 기본값 → 명시적 초기화 → 클래스 초기화 블럭 |
인스턴스 변수 | 인스턴스가 생성될 때마다, 각 인스턴스별로 | 기본값 → 명시적 초기화 → 인스턴스 초기화 블럭 → 생성자 |
📌 [중요] 클래스 변수는 항상 인스턴스 변수보다 먼저 생성되고 초기화됨
따라서 클래스 변수의 초기화가 모두 끝난 뒤에 인스턴스 변수의 초기화가 시작된다고 보면 됨