변수의 초기화
- 변수를 선언하고 처음으로 값을 저장하는 것
- 멤버변수(인스턴스변수,클래스변수)와 배열은 각 타입의 기본값으로 자동초기화되므로 초기화를 생략할 수 있다.
- 지역변수는 사용전에 꼭!!! 초기화를 해주어야한다.
인스턴스 변수 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();
}
}
'JAVA > 객체지향프로그래밍1' 카테고리의 다른 글
[JAVA] 생성자 this() / 참조변수 this (0) | 2021.06.21 |
---|---|
[JAVA]매개변수가 있는 생성자 (0) | 2021.06.21 |
[JAVA] 기본 생성자(default constructor) (0) | 2021.06.21 |
[JAVA] 가변인자(varargs)와 오버로딩 (0) | 2021.06.21 |
[JAVA] 오버로딩(overloading) (0) | 2021.06.21 |