본문 바로가기

프로그래밍/JAVA

[JAVA} 변수의 초기화

JAVA의 정석(2nd Editionm) (남궁 성 著) 200p~208p 를 참조해 코드를 작성했으며


개인적인 공부 내용을 적은 것이므로 오류가 있을 수 있습니다.


0. 들어가기에 앞서


들어가기에 앞서 변수에 대한 공부가 필요한 부분입니다.

(링크 : http://whatisthenext.tistory.com/37)


들어가기에 앞서, 변수의 종류에 대해서 숙지하고 가자.



자주 헷갈리는데,

1. 변수의 종류

인스턴스 변수(instance variable) : 인스턴스는 독립적인 공간을 서로 다른 개성을 갖는다.

클래스 변수(class variable) : 인스턴스 변수 앞에 static을 붙이면 모든 인스턴스가 같은 값을 공유한다

지역변수(local variable) : 메서드 내에 선언되어 메서드 내에서만 사용 가능하다. (매개변수 포함)


2. 멤버(member)

변수 + 메서드를 일컫는 말.


3. 멤버변수

<출처 : http://aventure.tistory.com/>


의미 : 메서드 밖에서 선언된 변수 (즉, 지역변수를 제외한 인스턴스변수, 클래스변수)

목적 : 객체의 "속성" 을 주는데 사용한다.

(나는 "속성"이란 뜻을 개성이라고 이해하고 싶다.)




1. 변수의 초기화


변수를 선언하고, 처음으로 값을 저장하는 것을 "변수의 초기화"라고 한다.


int i가 초기화 되지 않은 상태에서

int j = i 로 설정했으니 될리가 없다.


멤버변수(인스턴스 변수, 클래스변수)는 초기화를 하지 않아도 변수의 자료형에 맞게 기본값으로 초기화가 된다. 하지만 지역변수는 사용하기 전에 반드시 초기화를 해야 한다.


멤버변수(클래스 변수+인스턴스 변수)와 배열의 초기화는 선택적이다.

멤버 변수의 초기화 방법에는 3가지가 있다.


1. 명시적 초기화(explicit initialization)

2. 생성자(constructor)

3. 초기화 블럭(initialization block) (

- 인스턴스 초기화 블럭 : 인스턴스변수 초기화

-    클래스 초기화 블럭 : 클래스변수(static 변수) 초기화



2. 명시적 초기화(explicit initialization)


변수 선언과 동시에 초기화하는 것을 명시적 초기화라고 한다.

class Car {
int door = 4; // 기본형(primitive type) 변수의 초기화
Engine e = new Engine (); // 참조형(reference type) 변수의 초기화
}

가장 기본적이면서 간단한 초기화 방법이다. 가장 우선적으로 고려해야 할 초기화 방법이다.

변수를 선언함과 동시에 초기화한다.



3. 초기화 블럭(initialization block)


보다 복잡한 초기화 작업이 필요할 때 사용된다.


class InitBlock{
static { } // 클래스 초기화 블럭
{ } // 인스턴스 초기화 블럭
}


클래스 초기화 블럭 : "클래스 변수" 초기화에 사용

인스턴스 초기화 블럭 : "인스턴스 변수" 초기화에 사용


클래스 초기화 블럭 :  클래스가 메모리에 처음 로딩될 때 한번만 수행

인스턴스 초기화 블럭 : 생성자와 같이 인스턴스를 생성할 때 마다 수행

( ※ 생성자 보다 인스턴스 초기화 블럭이 먼저 수행)

( ※ 인스턴스 변수의 초기화는 주로 생성자를 쓰기 때문에, 인스턴스 초기화 블럭은 잘 사용하지 않음)


[참고] 

클래스가 처음 로딩될 때 클래스변수들이 자동적으로 메모리에 만들어지고나서 

바로 클래스 초기화 블럭이 클래스 변수들을 초기화한다.


인스턴스 변수의 초기화는 주로 생성자를 사용하기 때문에, 인스턴스 초기화 블럭은 잘 사용되지 않는다.

대신 클래스의 모든 생성자에서 공통적으로 수행되어져야 하는 코드가 있는 경우 생성자에 넣지 않고

인스턴스 초기화 블럭에 넣어 두면 코드의 중복을 줄일 수 있다.



모든 생성자에 공통적으로 수행해야 하는 문장이 존재한다.

System.out.println("Car인스턴스가 생성되었습니다."


인스턴스 초기화 블럭을 생성자보다 먼저 써줘야 한다.

이렇게 인스턴스 블럭을 이용하면 코드가 간결해지고 코드의 신뢰성과 오류 가능성을 줄여준다.



클래스 초기화 블럭 → 메인메서드 → BlockTest 인스턴스 생성→ 인스턴스 초기화 블럭  생성자 수행


위 예제의 시사점


1. BlockTest가 메모리에 로딩될 때, 클래스 초기화 블럭이 가장 먼저 수행된다.

2. 우리가 신경쓰지 않았던 메인메서드를 자세히 보면 인스턴스 초기화 블럭이 있다는 것.

3. 인스턴스 초기화 블럭은 인스턴스가 생성될 때 마다 수행된다.



명시적 초기화를 통해 배열 arr 생성

클래스 초기화 블럭을 통해 배열의 각 요소들을 random()으로 임의의 값으로 채움



4. 멤버변수의 초기화 시기와 순서


초기화 시점 

클래스변수 : 클래스가 처음 로딩될 때 단 한번 초기화

인스턴스변수 : 인스턴스가 생성될 때마다 각 인스터스별로 초기화가 이루어짐


초기화 순서

클래스변수    : 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭

인스턴스변수 : 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자


모든 인스턴스(personA, personB, personC)가 고유한 cardNum을 "공유"해야 하므로

count 변수를 static (즉, 클래스 변수)로 선언했다.


만약에 인스턴스 변수로 선언하면, 인스턴스가 생성될 때 마다 0으로 초기화 된다.