[자바의 정석] Chapter 6 객체 지향 프로그래밍 요약(6) - 변수의 초기화
변수의 초기화
o 변수를 선언하고 처음으로 값을 저장하는 것을 ‘변수의 초기화’리고 한다. 변수의 초기화는 선택적이지만 가능하면 선언과 동시에 초기화 하는 것이 적절하다.
o 멤버변수(클래스변수, 인스턴스변수)와 배열은 초기화를 하지 않을 경우 자동으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지나(선택적) 지역변수는 사용하기 전에 반드시 초기화를 해야한다. (필수적)
class InitTest {
int x;
int y=x; //인스턴스 변수 초기화 없이 사용가능, 자동 기본값 초기화
void method() {
int i;
int j=i; //에러, 지역 변수 초기화 하지 않고 사용
}
}
|
o 각 타입의 기본값은 다음과 같다.
자료형 |
기본값 |
boolean |
false |
char |
‘\u0000’ |
byte, short, int |
0 |
long |
0L |
float |
0.0f |
double |
0.0d 또는 0.0 |
참조형 변수 |
null |
o 멤버변수의 초기화 방법은 여러가지가 있다.
1. 명시적 초기화(explicit initialization)
2. 생성자(constructor)
3. 초기화 블록(initialization block)
: 인스턴스 초기화 블록 – 인스턴스 변수를 초기화 하는데 사용
: 클래스 초기화 블록 – 클래스 변수를 초기화 하는데 사용
명시적 초기화(explicit initialization)
o 변수를 선언과 동시에 초기화하는 것을 명시적 초기화라고 한다. 가장 기본이면서 간단한 초기화 방법이기에 여러 초기화 방법 중에서 가장 먼저 고려되어야 한다.
class Car {
int door = 4; // 기본형 변수 초기화
Engine e =new Engine(); // 참조형 변수 초기화
}
|
o 명시적 초기화보다 복잡한 초기화 작업이 필요할 때는 초기화 블록 또는 생성자를 사용한다.
초기화 블록(initialization block)
o 초기화 블록은 ‘클래스 초기화 블록’과 ‘인스턴스 초기화 블록’ 두 가지 종류가 있다.
- 클래스 초기화 블록 : 클래스 변수의 복잡한 초기화에 사용된다.
- 인스턴스 초기화 블록 인스턴스 변수의 복잡한 초기화에 사용된다.
o 인스턴스 블록은 클래스 내에 블록{ }을 만들고 작성하면 되며 클래스 초기화 블록은 인스턴스 초기화 블록 앞에 static을 붙이면 된다.
class InitBlock {
{/*인스턴스 초기화 블럭*/ }
static {/*클래스 초기화 블럭*/}
}
|
o 초기화 블록 내에서는 메서드와 같이 조건문, 반복문, 예외처리 구문 등을 자유롭게 사용이 가능하기에 명시적 초기화로는 부족한 복잡한 초기화 작업이 필요한 경우 사용한다.
o 클래스 초기화 블록은 클래스가 메모리에 처음 로딩될 때 한 번만 수행되며, 인스턴스 초기화 블록은 생성자와 같이 인스턴스를 생성할 때 마다 수행된다.
o 클래스가 처음 로딩될 때 클래스변수들이 자동적으로 메모리에 만들어지고, 곧바로 초기화 블록이 클래스 변수들을 초기화하기에 생성자보다 초기화 블록이 먼저 수행된다.
o 초기화 블록이 생성자와 다른 점은 인스턴스 생성 시 생성자는 입력 받는 매개변수에 따라 초기화 값이 다르게 적용될 수 있지만 초기화 블록은 고정된 값으로 초기화 한다.
class Car {
int count, serialNo;
String color;
String gearType;
{ // 생성자에서 공통으로 수행되어야 하는 작업은
// 인스턴스 초기화 블록을 사용하여 수행한다.
count++;
serialNo = count;
}
Car() {
// 중복되는 되는 작업 인스턴스 초기화 블록으로 수행
// count++;
// serialNo = count;
color = "Write";
gearType = "Auto";
}
Car(String color, String gearType) {
// count++;
// serialNo = count;
this.color = color;
this.gearType = gearType;
}
}
|
o 코드의 중복성을 제거함으로써 코드의 신뢰성을 높이고 오류 발생가능성을 줄여 주는 장점이 있다. 재사용성을 높이고 중복을 제거하는 것이 객체지향 프로그래밍이 추구하는 궁극적인 목표이다.
public class Test {
static {System.out.println("static 초기화 블럭 실행");}
{System.out.println("인스턴스 초기화 블럭 실행");}
public Test() {
System.out.println("생성자 실행");
}
public static void main(String[] args) {
System.out.println("bt 객체 생성");
Test bt = new Test();
System.out.println("bt2 객체 생성");
Test bt2 = new Test();
}
}
|

- 코드가 실행하면서 Test가 메모리에 로딩될 때, static 초기화 블록이 제일 먼저 실행되고 main메서드가 수행된다. 그 다음 인스턴스 생성으로 인스턴스 초기화 블록이 실행되고 생성자가 실행된다.
- 클래스 초기화 블록은 처음 메모리에 로딩될 때 한 번만 수행되고 인스턴스 초기화 블록은 인스턴스 생성 시 마다 수행된다.
멤버변수의 초기화 시기와 순서
o 프로그램 실행 도중 클래스에 대한 정보가 요구될 때, 클래스는 메모리에 로딩된다.
예) 클래스 멤버 사용, 인스턴스 생성 등
o 하지만 해당 클래스가 이미 메모리에 로딩되어 있다면, 다시 로딩 하지 않으며 초기화도 수행하지 않는다.
클래스 변수의 초기화 시점 |
클래스가 처음 로딩될 때 단 한 번 초기화 된다. |
인스턴스 변수의 초기화 시점 |
인스턴스가 생성될 때마다 각 인스턴스 별로 초기화가 이루어진다. |
|
|
클래스 변수의 초기화 순서 |
기본값 -> 명시적 초기화 -> 클래스 초기화 블록 |
인스턴스 변수의 초기화 순서 |
기본값 -> 명시적 초기화 -> 인스턴스 초기화 블록 -> 생성자 |
class InitTest{
// 명시적 초기화
static int cv=1;
int iv=1;
// 클래스 초기화 블럭
static { cv=2; }
// 인스턴스 초기화 블럭
{ iv=2; }
// 생성자
InitTest(){
iv=3;
}
}
|
- 클래스 변수 초기화 (1~3) : 클래스가 처음 메모리에 로딩될 때 차례대로 수행된다.
- 인스턴스 변수 초기화(4~7) : 인스턴스를 생성할 때 차례대로 수행된다.
1. cv가 메모리(method area)에 생성되고, cv에는 int형의 기본값인 0이 cv에 저장된다.
2. 그 다음 (클래스)명시적 초기화(static int cv=1)에 의해 변수 cv에 1이 저장된다.
3. 마지막으로 클래스 초기화 블록이 수행되어 변수 cv에 2가 저정된다.
4. InitTest클래스의 인스턴스가 생성되면서 iv가 메모리(heap)에 존재하게 된다. iv역시 int형 변수이므로 기본값 0이 저장된다.
5. (인스턴스)명시적 초기화에 의해서 iv에 1이 저장된다.
6. 인스턴스 초기화 블록이 수행되어 iv에 2가 저장된다.
7. 마지막으로 생성자가 수행되어 iv에는 3이 저장되게 된다.
- 클래스가 이미 메모리에 로딩되어 있기에 클래스 변수에 대해서는 다시 초기화를 수행하지 않는다.
o 예제 1
class Product {
static int count;
int serialNo;
{
count++;
serialNo=count;
}
public Product() {}
}
public class Test {
public static void main(String[] args) {
Product p1 = new Product();
Product p2 = new Product();
Product p3 = new Product();
System.out.println("p1의 제품번호(serialNo)는 " + p1.serialNo);
System.out.println("p2의 제품번호(serialNo)는 " + p2.serialNo);
System.out.println("p3의 제품번호(serialNo)는 " + p3.serialNo);
System.out.println("생상된 제품의 수는 모두 "+Product.count+"개 입니다.");
}
}
|
- Product클래스의 인스턴스를 생성할 때마다 인스턴스 블록이 수행되어 클래스 변수 count를 1증가시킨 다음 serialNo변수에 대입한다. 이렇게 하여 새로 생성된 인스턴스는 이전에 생성된 인스턴스 값보다 1 증가한 값을 갖게 된다.
- count를 인스턴스 변수로 선언했다면 인스턴스 생성이 될 때마다 0으로 초기화되어 새로운 인스턴스 생성을 하여도 serialNo값은 항상 1이 된다.
o 예제 2
class Document{
static int count = 0;
String name; //문서명 (Document name)
Document(){
this("제목없음"+ ++count);
}
Document(String name) {
this.name = name;
System.out.println("문서 " + this.name + "가 생성되었습니다.");
}
}
public class Test {
public static void main(String[] args) {
Document d1 = new Document();
Document d2 = new Document("자바.txt");
Document d3 = new Document();
Document d4 = new Document();
}
}
|