10. 멤버 변수 초기화 및 순서
변수 초기화
우선 멤버 변수(인스턴스 변수, 클래스 변수)와 지역 변수의 초기화 차이를 알아보겠습니다.
지역 변수의 경우에는 우리가 직접 초기화 해주어야 하고, 멤버 변수의 경우 자동으로 초기화가 이루어집니다.
1
2
3
4
5
6
7
8
|
class variableExam {
int a;
int b;
void localVariable {
int x;
int y = x;
}
|
cs |
위 예제의 6행부터 7행까지를 살펴보시면 지역변수는 직접 초기화 해주지 않으면 어떠한 값도 담기지 않게 됩니다. 따라서 7행에서
변수 y에 값을 모르는 x를 대입하려고 하기 때문에 에러가 발생하게 됩니다.
반대로 2행부터 3행의 인스턴스 변수를 보시면 직접 값을 담아주지 않아도 7행과 같이 int b = a; 코드를 사용하여도 에러없이
자동으로 기본값 0이 초기화되어 출력된다는 것을 확인할 수 있습니다.
-------- 이해가 안되신다면 아래의 이유 부분은 건너 띄어주세요! --------
이유) 이전에 JVM 메모리 구조에서 다뤘던 호출스택에 올라가는 메서드들이 사용되었다가 실행이 끝나면 종료가 반복되며
이 공간을 반복적으로 사용하게 될 것입니다. 그런데 만약 이때 메서드가 하나하나 호출될 때 마다 값을 0으로 초기화 하면 성능이 매우
떨어지게 됩니다. 따라서 기존에 쓰던 값에서 새로운 값으로 덮어 씌우는 방식으로 해당 영역을 사용하게 됩니다. 즉 덮어 씌울 이 값을 직
접 지정해주지 않으면 그 값이 무엇인지 알 수 없는 것입니다. 반대로 힙 영역에서 사용되는 인스턴스 변수의 특성상 지역 변수에 비해 오
랫동안 남아 있게되므로 기본값으로 자동으로 초기화해 주게 됩니다. ex) boolean - false, int - 0, float - 0.0f 등등
멤버변수 초기화 방식
멤버변수를 초기화하는 방식에 크게 네 가지로 나뉩니다.
첫 번째는 자동으로 초기화되는 방식입니다. 멤버 변수의 경우 초기화 해주지 않아도 기본값으로 자동으로 초기화가 이루어
지고, 명시적 혹은 블록 등을 이용해 초기화 해주어도 우선적으로 자동으로 초기화가 먼저 진행됩니다!
두 번째는 명시적으로 초기화해주는 방식입니다. int a = 2; 와 같이 대입 연산자(=)를 통해 우리가 흔히 사용해오던 간단한
방식으로 초기화해주는 것이 되겠습니다.
+ 참조변수 초기화란? ) 기본 타입형은 단순 값을 대입한다로 쉽게 이해할 수 있지만, 참조형 변수는 와닿지 않으실 것이라 생각합니다.
Refrigerator R = new Refrigerator(); 와 같이 인스턴스를 생성했을 때, 참조변수는 R이 되는데 이 참조변수 R에는 해당 인스턴스(객체)의
주소값이 담겨지게 됩니다. 단순히 Refrigerator R; 로 선언하였다면 기본값인 null 값이 되겠죠?
세 번째는 초기화 블록을 이용하는 방식입니다. 예를 들어 여러 변수들도 초기화 해주어야 하고, 반복문도 사용하는 그러한 메서드를 사용
하고 싶습니다. 그러면 이때에는 단순 대입 연산자(=)를 통해 할 수 있는 범위를 넘어서기 때문에 블록 { } 으로 묶어서 이를 초기화해주는
방식이 되겠습니다.
네 번째는 생성자를 이용하는 방식입니다. 앞서 다루었던 생성자 글에서 많이 다루었으므로 생략하도록 하겠습니다!
초기화 시점 비교(인스턴스 변수 vs 클래스 변수)
앞서 다루었던 JVM 메모리 구조를 보셨다면 쉽게 이해가 될 것이라 생각합니다!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Test1 {
static int classVariable = 1;
int InstanceVariable = 2;
static { classVariable = 3; }
{InstanceVariable = 4; }
Test1() {
InstanceVariable = 5;
}
}
|
cs |
우선 class Test1이 쓰이면서 메모리(메서드 영역)에 올라가면서 단 한번의 초기화가 이루어집니다.
int형 이므로 클래스 변수 classVariable의 값은 기본값은 우선 0으로 자동 초기화 되고, 이후 2행의 명시적 초기화 방식을 통해 1로 초기화
됩니다. 마지막으로 초기화 블록 방식을 통해 3으로 초기화됩니다.
호출 스택에 올라가는 인스턴스 변수는 클래스 변수의 초기화가 모두 끝난 시점에서 진행됩니다. 따라서 클래스 변수의 초기화가 끝난 후
순차적으로 인스턴스 변수이 초기화가 마찬가지로 진행됩니다.
순서를 정리해보면 다음과 같습니다.
1. 클래스 변수의 자동 초기화
2. 2행 클래스 변수 명시적 초기화
3. 6행 블록 방식을 통한 클래스 변수 초기화
4. 인스턴스 변수의 자동 초기화
5. 4행 인스턴스 변수 명시적 초기화
6. 8행 블록 방식을 통한 인스턴스 변수 초기화
7. 생성자를 통한 인스턴스 변수 초기화