변수의 초기화
변수를 선언하고 처음으로 값을 저장하는 것을 '변수의 초기화'라고 한다.
변수의 초기화는 경우에 따라서 필수적이기도 하고 선택적이기도 하지만,
가능하면 선언과 동시에 적절한 값으로 초기화 하는 것이 바람직하다.
멤버변수는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로
초기화하지않고 사용해도 되지만,
지역변수는 사용하기 전에 반드시 초기화해야 한다.
class InitTest{
int x; //인스턴스변수
int y = x; //인스턴스변수
void method() {
int i; //지역변수
int j = i; //에러. 지역변수를 초기화하지 않고 사용
}
}
인스턴스변수 x는 초기화 해주지 않아도 자동적으로 int형의 기본값인 0으로 초기화되므로
에러가 발생하지 않지만,
method()의 지역변수 i는 자동적으로 초기화되지 않으므로, 초기화 되지 않은 상태에서
변수 j 를 초기화하는데 사용될 수 없다.
명시적 초기화
변수를 선언과 동시에 초기화하는 것을 명시적 초기화라고 한다.
가장 기본적이면서도 간단한 초기화 방법이므로
여러 초기화 방법 중에서 가장 우선적으로 고려되어야 한다.
하지만 복잡한 초기화 작업이 필요할 때는 '초기화 블럭'또는 생성자를 사용해야 한다.
초기화 블럭
초기화 블럭에는 클래스 초기화 블럭과 인스턴스 초기화 블럭 두 가지 종류가 있다.
클래스 초기화 블럭은 클래스변수의 초기화에 사용되고,
인스턴스 초기화 블럭은 인스턴스 변수의 초기화에 사용된다.
초기화 블럭 내에는 메소드 내에서와 같이 조건문, 반복문, 예외처리구문 등을 자유롭게 사용할 수 있으므로,
초기화 작업이 복잡하여 명시적 초기화만으로는 부족한 경우 초기화 블럭을 사용한다.
인스턴스 초기화 블럭은 단순히 클래스 내에 블럭 { } 을 만들고,
클래스 초기화 블럭은 인스턴스 초기화 블럭 앞에 단순히 static을 덧붙이기만 하면 된다.
클래스 초기화 블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수행되며,
인스턴스 초기화 블럭은 생성자와 같이 인스턴스를 생성할 때 마다 수행된다.
다음과 같이 인스턴스 변수의 초기화는 주로 생성자를 사용하고,
인스턴스 초기화 블럭은 모든 생성자에서 공통으로 수행돼야 하는 코드를 넣는데 사용한다.
Car() {
count ++;
serialNo = count;
color = "white";
geartype = "auto";
}
Car(String color, String geartype){
count ++;
serialNo = count;
this.color = color;
this.geartype = type;
}
위와 같은 클래스의 모든 생성자에 공통으로 수행되어야 하는 문장들이 있을 때,
이 문장들을 각 생성자마다 써주기 보다는 인스턴스 블럭에 넣어주면 코드가 보다 간결해진다.
{
count ++;
serialNo = count;
}
밑의 실습프로그램을 살펴보자.
예제가 실행되면서 BlockTest가 메모리에 로딩될 때, 클래스 초기화 블럭의 가장먼저 수행된다.
다음, main메소드가 수행되어 인스턴스가 생성되면서 인스턴스 초기화블럭이 먼저 수행되고
끝으로 생성자가 수행되는 것을 알 수 있다.
위의 실행결과에서도 알 수 있듯이 클래스 초기화 블럭은 처음 메모리에 로딩될 때 한번만 수행되었지만,
인스턴스 초기화 블럭은 인스턴스가 생성될 때 마다 수행되었다.
멤버변수의 초기화 시기와 순서
클래스 변수의 초기화 시점은 클래스가 처음 로딩될 때 단 한번 초기화 된다.
인스턴스 변수의 초기화 시점은 인스턴스가 생성될 때마다 각 인스턴스별로 초기화가 이루어진다.
그럼 초기화 순서는 어떻게 될까?
다음 예시를 통해 살펴보자.
class InitTest{
static int cv = 1; //명시적초기화
int iv = 1; //명시적초기화
static { c v = 2; } //클래스 초기화 블럭
{ iv = 2; } //인스턴스 초기화 블럭
InitTest() { iv = 3; } //생성자
new InitTest() ; 와 같이 인스턴스를 생성했을 때, cv와 iv가 각각 초기화 되는과정을 순서대로 살펴보자.
여기서 생각할 점은 클래스변수는 항상 인스턴스변수보다 먼저 생성되고 초기화 된다는 점이다.
1. cv가 메모리에 생성되고, cv에는 int형의 기본값인 0이 cv에 저장된다. (기본값)
2. 그 다음에는 명시적 초기화(int cv = 1)에 의해서 cv에 1이 저장된다. (명시적 초기화)
3. 마지막으로 클래스 초기화 블럭(cv = 2)이 수행되어 cv에는 2가 저장된다. (클래스 초기화 블럭)
4. InitTest클래스의 인스턴스가 생성되면서 iv가 메모리에 존재하게 된다. (기본값)
5. 명시적 초기화에 의해서 iv에 1이 저장되고 (명시적 초기화)
6. 인스턴스 초기화 블럭이 수행되어 iv에 2가 저장된다. (인스턴스 초기화 블럭)
7. 마지막으로 생성자가 수행되어 iv에는 3이 저장된다. (생성자)
마지막 예시를 살펴보며 정리를 다시 한번 해보자.
Document클래스의 인스턴스를 생성할 때 마다 생성자가 수행되어,
클래스변수 count의 값을 1을 증가시킨다.
만일 count를 인스턴스 변수로 선언했다면,
인스턴스가 생성될 때마다 0으로 초기화 될 것이므로 count의 값은 항상 1이 될 것이다.
그래서 count는 클래스 변수로 선언해주었다.
'JAVA > Basic' 카테고리의 다른 글
[JAVA-basic] 상속(2) (0) | 2021.08.18 |
---|---|
[JAVA-basic] 상속 (0) | 2021.08.18 |
[JAVA-basic] 생성자 (0) | 2021.08.13 |
[JAVA-basic] 변수와 메소드(2) (0) | 2021.08.13 |
[JAVA-basic] 변수와 메소드 (0) | 2021.08.11 |