이번 글에서는 자바의 변수들이 어떻게 초기화되는지 그리고 각 변수들(인스턴스 변수, 클래스 변수, 지역 변수)들의 초기화 순서에 대해 알아보겠습니다.
인스턴스 변수와 클래스 변수는 변수의 선언이 없을 경우 디폴트 값으로 지정되어 있습니다.
변수 a, b, c, d, e, f, g를 출력하면
이렇게 값을 초기화하지 않아도 인스턴스와 클래스 변수는 타입에 따라 디폴트 값으로 정해지게 됩니다.
그렇다면 초기화의 순서는 어떻게 될까요? 위에서 아래로 차례대로 a, b, c, d ~ h 순서로 될까요?
위의 코드의 a,b,c 의 값이 어떻게 될까요?
음... a는 초기화가 선언되지 않았으니 디폴트 값 0일 테고 b는 a에서 1 올린 값과 같아지니 b = 1 가 될 테고 c값은 1인 a를 다시 1 올린 값과 같아지니 c = 2 이 돼서 a = 2, b = 1 c = 2 가 되겠구나!라고 생각할 수 있습니다.
그런데 말이죠. 실제로 값을 보니 a =2, b = 2, c = 1입니다 응? 왜 b랑 c의 값이 왜 이러지 라고 생각할 수 있을 것입니다.
사실은 그렇습니다. 클래스 변수와 인스턴스 변수들 중 항상 클래스 변수가 먼저 초기화된 뒤에 인스턴스 변수가 초기화됩니다. 바로 이 부분이 오늘의 핵심 내용인 거죠.
보다 정확하게 말하면 클래스 변수는 클래스가 메모리에 올라갈 때 선언되고 인스턴스 변수는 객체가 생성될 때 실행됩니다. 그래서 객체 1을 선언하기 전 이미 a = 1 , c = 1입니다.
이를 확인하기 위해 객체를 생성하지 않은 채 아래의 코드를 메인에다가 입력하면
System.out.println("a = "+variable_lecture.a);
System.out.println("b = "+variable_lecture.c);
a = 1
c = 1 이 출력이 됩니다.
이제 객체를 생성하겠습니다. int b = ++a 코드가 실행됩니다. 결과적으로 a = 2, b = 2, c = 1 이 됩니다.
그럼 다시 한번 객체를 생성해보겠습니다. 이제 객체는 총 2개입니다. 그렇다면 2번째 객체를 생성하고 난 뒤의 a, b, c 값은 어떻게 될까요? 그전에 다시 한번 클래스 변수와 인스턴스 변수에 대해 복습해 보자면 클래스 변수는 클래스가 메모리에 올라갈 때 선언되며 모든 객체가 공통으로 가지는 값이라고 했고 인스턴스 변수는 객체가 생성될 때 각 객체마다 가지는 독립적인 값입니다.
2번째 객체를 생성했습니다. 과연 a, b, c의 값이 어떻게 변했을까 살펴보도록 합시다.
일단 2번 객체에서 나온 값은 a =3, b = 3, c = 1입니다. 왜 그런 걸까요? 사실은 이미 객체 1개를 생성하기도 전에
static int a; static int c = ++a; 는 선언되었기 때문에 객체가 생성된다고 다시 이 코드가 실행되지 않습니다. 분명히 클래스가 메모리에 올라갈 때 한번 실행되기 때문이죠.
그래서 객체 2가 생성될 때 int b = ++a; 코드만 실행됩니다. 앞서 a = 2 가 됐기 때문에 b = 3 , a = 3 이 됩니다.
다시 한번 이전에 생성했던 객체 1을 살펴보겠습니다. 분명히 a = 2, b = 2, c = 1 이였는데...
응???? a = 3 이 되었습니다. 근데 b = 2 여전히 변함없습니다. 네 또 한번 말하자면 클래스 변수는 모든 객체가 공통으로 가지는 값입니다. 객체 2로 인해 클래스 변수 a = 3 이 되었고 이는 객체 1 에도 영향을 주기 때문이죠.
즉 객체 1이 생성된 후 클래스 변수 a = 2, c = 1입니다. 그리고 객체 2를 생성할 때 a = 2 , c = 1 인 상태에서 시작하게 됩니다. 반대로 인스턴스 변수 b는 값이 초기화되지 않은 상태인 b = 0에서 새로 시작하게 됩니다.
그리고 마지막으로 다들 아시겠지만 지역변수는 초기화가 반드시 필요합니다. 그리고 메서드 내에서만 존재하고 메서드가 실행될 때 메모리에 올라갔다가 메서드 종료 때 메모리에서 사라져 버립니다.
두 메서드에서 int x는 제각기 다른 존재입니다. 그리고 지역변수는 초기화 없이 사용할 수 없습니다.
지역변수를 초기화하지 않으면 에러가 발생합니다. 지역변수를 반드시 초기화해줘야 하는 이유는 지역변수는 메서드 내에서 계산을 위해 쓰일 목적으로 만들어지는데 초기화되어 있지 않으면 메서드를 실행 시 예기치 않은 값이 될 수 있기 때문입니다. 그래서 컴파일러가 이러한 상황이 발생하는 것을 피하기 위해 프로그래머에게 초기화할 것을 요청하게 됩니다.
이번 글에서 초기화 블록까지 다뤄볼려 했는데 분량 초과로 다음 글에서 소개 하도록 하겠습니다.
'자바' 카테고리의 다른 글
자바 클래스? 객체지향? (0) | 2019.11.08 |
---|---|
자바 클래스 초기화 블럭 (0) | 2019.11.01 |
클래스변수, 인스턴스변수, 지역변수 (0) | 2019.10.04 |
오버로딩과 오버라이딩의 차이 (0) | 2019.09.27 |
오버라이딩, overriding (0) | 2019.09.21 |