JAVA/객체지향프로그래밍1

[JAVA] 변수의 초기화

prize1209 2021. 6. 21. 18:25

변수의 초기화

- 변수를 선언하고 처음으로 값을 저장하는 것

- 멤버변수(인스턴스변수,클래스변수)와 배열은 각 타입의 기본값으로 자동초기화되므로 초기화를 생략할 수 있다.

- 지역변수는 사용전에!!! 초기화를 해주어야한다.

 

인스턴스 변수 x는 초기화를 해주지 않아도 자동적으로 int형의 기본값인 0으로 초기화되므로, 

'int y= x' 와 같이 할 수 있다. x의 값이 0이므로 y역시 0이 저장된다. 

하지만 method1()의 경우, 지역변수는 자동적으로 초기화되지 않으므로, 모르는 i의 값을 j에 넣으려고 하다보니 에러.

 

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

 

 

각 타입의 기본값 

 

 

 

▶멤버변수의 초기화 방법

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

2. 생성자(constructor)

3. 초기화 블럭(initialization block)

-인스턴스 초기화 블럭 : 인스턴스변수를 초기화하는데 사용

-클래스 초기화 블럭: 클래스변수를 초기화 하는데 사용 

 

 

 

 

 

멤버 변수의 초기화(explicit initialization)

 

1)명시적 초기화(=)

선언 시 대입연산자를 이용

 

참조형은 객체를 만들어서 넣어줘야한다. 

참조형 변수가 가질 수 있는 값은 null(기본값) 아니면 객체의 주소다. 

 

 

 

2)초기화 블럭(initialization block)

 

'클래스 초기화 블럭'과 '인스턴스 초기화 블럭' 두 가지가 있다. 

 

클래스 초기화 블럭     클래스 변수의 복잡한 초기화에 쓴다.

인스턴스 초기화 블럭  인스턴스변수의 복잡한 초기화에 쓴다.  

 

iv-인스턴스 초기화 블럭: { } 

cv-클래스 초기화 블럭 : static { }

 

 

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

인스턴스 변수 초기화 시점: 인스턴스가 생성될 때마다 

 

생성자보다 인스턴스 초기화 블럭이 먼저 수행된다. 

 

클래스 초기화 예)

 

인스턴스 변수의 초기화는 주로 생성자를 사용하고,

인스턴스 초기화 블럭은 모든 생성자에서 공통으로 수행돼야하는 코드를 넣는데 사용한다. 

 

 

 

3) 생성자 

-iv 초기화, 복잡한 초기화

 

 

 

 

예27)

public class BlockTest {
	static {// 클래스 초기화 블럭
		System.out.println("static{ }");
	}
	{// 인스턴스 초기화 블럭
		System.out.println("{ }");
	}

	public BlockTest() {
		System.out.println("생성자");
	}

	public static void main(String[] args) {
		System.out.println("BlockTest bt = new BlockTest();");
		BlockTest bt = new BlockTest();

		System.out.println("BlockTest bt2 = new BlockTest();");
		BlockTest bt2 = new BlockTest();
	}
}

BlockTest 가 메모리에 로딩될 때, 클래스 초기화 블럭이 가장 먼저 수행되어 'static { }'이 화면에 출력된다. 

그 다음에 main 메서드가 실행되어 BlockTest인스턴스가 생성되면서 인스턴스 초기화 블럭이 먼저 수행되고, 끝으로 생성자가 수행된다. 

->클래스 초기화 블럭은 처음 메모리에 로딩될 때 한번 수행되었지만, 인스턴스 초기화 블럭은 인스턴스가 생성될 때마다 수행되었다. 

 

 

예28)

public class StaticBlockTest {
	static int[] arr = new int[10];

	static {
		for (int i = 0; i < arr.length; i++) {
			// 1과 10 사이의 임의의 값을 배열 arr에 저장한다.
			arr[i] = (int) (Math.random() * 10 + 1);
		}

	}

	public static void main(String[] args) {
		for (int i = 0; i < arr.length; i++) {
			System.out.println("arr[" + i + "]:" + arr[i]);
		}
	}
}

명시적 초기화를 통해 배열 arr을 생성하고, 클래스 초기화 블럭을 이용해 배열의 각 요소들을 random()을 사용해서 임의의 값을 넣었다. 배열이나 예외처리 등 복잡한 초기화에서는 추가적으로 클래스 초기화 블럭을 사용한다. 

 

 

 

 

 

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

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

▶ 인스턴스변수 초기화 시점 : 인스턴스가 생성될 때 마다 각 인스턴스별로 초기화가 이루어진다. 

 

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

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

 

 

 

객체를 또 만들면 1,2,3은 실행되지 않는다. (cv는 처음 로딩될 때 한번만 초기화되므로)

 

초기화 순서

1.cv->iv

2. 자동->간단->복잡 

0 ->=->static{} 생성자 

 

 

 

예29)

class Product {
	static int count = 0; // 생성된 인스턴스의 수를 저장하기 위한 변수
	int serialNo; // 인스턴스 고유의 번호

	{// 인스턴스 초기화
		count++;
		serialNo = count;
	}

}

public class ProductTest {
	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);

	}
}

Product 클래스의 인스턴스를 생성할 때마다 인스턴스 블럭이 수행되어, 클래스변수 count의 값을 1증가시킨 다음,

그 값을 인스턴스 변수 serialNo에 저장한다. 

새로 생성되는 인스턴스는 이전에 생성된 인스턴스보다 1 증가된 serialNo을 갖게 된다. 

 

생성자가 하나 밖에 없기 때문에 인스턴스 블럭 대신, Product 클래스의 생성자를 사용해도 결과는 같지만,

코드의 의미상 모든 생성자에서 공통으로 수행되어야하는 내용이라서 인스턴스 블럭을 사용했다. 

 

만일 , count를 인스턴스 변수로 선언했다면, 인스턴스가 생성될 때마다 0으로 초기화될 것이므로 모든 Product 인스턴스의 serialNo의 값은 항상 1이다. 

 

 

 

예30)

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 DocumentTest {
	public static void main(String[] args) {
		Document d1 = new Document();
		Document d2 = new Document("자바.txt");
		Document d3 = new Document();
		Document d4 = new Document();
	}
}