Developer/JAVA

JAVA , 초기화 블럭(init) 과 생성자 , this

단님 2024. 8. 4. 00:20
728x90
init
(초기화 블럭)
초기화 블럭의 역할

 

멤버변수의 초기화를 할 수 있다. (= 명시적 초기화)

초기화가 복잡할 경우, 생성자를 이용할 것. 생성자는 이후에 다뤄보겠다.

 

자바의 수행 순서

 

프로그램 로딩 ☞ 클래스 초기화 블럭(stack)  ☞ main 메서드 실행

☞ 인스턴스 생성 (new)(heap)  ☞ 인스턴스 초기화 블럭 ☞ 생성자 실행

 

여기서 봐야할 점은 , main 실행전 클래스 초기화 블럭이 실행되고 , 

main 실행 후 생성자 실행 전에 인스턴스 초기화 블럭이 실행된다는 것이다.

 

	static int [] arr = new int[10]; //선언만 해놓음.
	static int count = 100; // 선언과 동시에 명시적으로 초기화
	
	String color ; // 선언만 해놓음.
	double num = 123.456; // 선언과 동시에 명시적으로 초기화 
    
    
    static {
		
	} // static의 초기화 블럭
	
	{
		
	}// instance 의 초기화 블럭

 

위 코드와 같이 빈 중괄호의 영역은 instance 의 초기화 블럭 이고 ,

static 중괄호의 영역은 static의 초기화 블럭이다.

 

초기화 블럭과 함께
실행 순서 확인해보기
static {
	System.out.println("static의 초기화 블럭");
} // static의 초기화 블럭
	
{
	System.out.println("instance의 초기화 블럭");
}// instance 의 초기화 블럭
	
public static void main(String[] args) {
	System.out.println("main 메서드의 실행 블럭");
}

 

프로그램 로딩 ☞ 클래스 초기화 블럭(stack)  ☞ main 메서드 실행
☞ 인스턴스 생성 (new)(heap)  ☞ 인스턴스 초기화 블럭 ☞ 생성자 실행

 

2. 변수를 초기화 해보기

 

static int [] arr = new int[10]; //선언만 해놓음.
static {
	System.out.println("static의 초기화 블럭===");
	// static 변수 arr 초기화 : random 으로 2자리수 임의의 정수 채우기
	for (int i = 0; i < arr.length; i++) {
		arr[i]=(int)(Math.random()*89+11);
	}
	System.out.print("static의 초기화 블럭 arr : ");
	for (int i : arr) {
		System.out.print(i+" ");
	}
	System.out.println();
	System.out.println("static의 초기화 블럭===");
} // static의 초기화 블럭
public static void main(String[] args) {
	System.out.println("main 메서드의 실행 블럭===");
	System.out.print("main 메서드 실행 블럭 arr : ");
	for (int i : arr) {
		System.out.print(i+" ");
	}
	System.out.println();
	System.out.println("main 메서드의 실행 블럭===");
}

 

선언만 해놓은 배열에 초기화 블럭을 이용하여 값을 넣었다.

메인메서드의 실행에서 static 변수인 배열에 값이 잘 들어가있는 것을 확인 할 수 있다.

 

그런데 왜 인스턴스 초기화 블럭은 실행되지 않았을까 ? 

실행문을 넣어두었었는데 말이다.

그 즉슨 , main 실행시 new 연산자를 통하여 인스턴스객체가 생성될때 실행되기 때문이다.

 

3. 인스턴스 초기화 블럭 보기
프로그램 로딩 ☞ 클래스 초기화 블럭(stack)  ☞ main 메서드 실행
 인스턴스 생성 (new)(heap)  ☞ 인스턴스 초기화 블럭 ☞ 생성자 실행
{
	System.out.println("instance의 초기화 블럭===");
	color = "blue";
	num = Math.random()*10+1;
	count = 12345; //static 변수 까지 사용 가능함을 알 수 있음.
	System.out.println("instance의 초기화 블럭===");
}// instance 의 초기화 블럭

 

System.out.println("인스턴스 생성 전 count :"+count);
//instance의 초기화 블럭
Ex06_initBlock ex06 = new Ex06_initBlock(); //인스턴스 생성
System.out.println("인스턴스 생성 후 count :"+ count);
Ex06_initBlock ex061 = new Ex06_initBlock(); //두번째 인스턴스 생성
System.out.println("두번째 인스턴스 생성 후 count :"+ count);

생성을 두번하면서 두번의 인스턴스 초기화 블럭이 실행 됨을 볼 수 있다.


 

생성자 (Constructor)

 

생성자란?

 

new 연산자를 통해 인스턴스객체가 생성될때 호출되는 특별한 기능의 메서드이다.

생성자는 클래스의 인스턴스를 초기화 하는 역할을 하고 , 클래스와 동일한 이름을 가진 메서드이다.

메서드의 오버로딩이 적용되어 , 기본 생성자와 매개변수가 있는 생성자로 나누어 볼 수 있다.

return 이 올 수 없고 , 메서드에 명시하는 타입 또는 void 또한 오지 않는다.

생성시에 단 한번 호출된다.

생성자를 따로 만들지 않으면 컴파일러가 자동으로 기본생성자 하나를 만들어 놓는다.

하지만 하나라도 만들게 되면 , 기본생성자를 만들어 놓지 않기 때문에,

매개변수를 활용한 생성자를 만들때는 , 꼭 기본생성자를 만들어 놓는 습관을 가질것.

생성 과정 살펴보기

 

new 연산자가 해당되는 클래스를 메모리에 로드해서 생성한다. 이때 생성 직후, 생성자 메서드를 호출.

기본 생성자 확인해 보기
	//생성자 메서드 추가
	// 클래스와 이름이 똑같아야함.
	public Ex06_initBlock () {
		System.out.println("생성자 실행");
	}//return 이 올 수 없음. , return의 명시의 타입 또는 void가 오지 않음.

프로그램 로딩 ☞ 클래스 초기화 블럭(stack)  ☞ main 메서드 실행
☞ 인스턴스 생성 (new)(heap)  ☞ 인스턴스 초기화 블럭  ☞ 생성자 실행

 

수업이 끝나고 ,

만약 static 변수로 인스턴스생성자를 통하거나 인스턴스 초기화 블럭을 통해 카운트를 증가시키면,

그 변수는 인스턴스 생성의 횟수를 말하는 거겠네 ? 라는 생각을 했다.

 

this , this()

 

this : 생성자 내에서 자기 자신의 인스턴스를 지칭하는 용어.

this() : 인자의 갯수와 타입이 일치하는 생성자를 호출하여 불러들임.

 

* this 사용 주의 사항 : this 는 사용하게 된다면 반드시 생성자 메서드 내 첫줄에 위치해야 한다.

 

매개변수가 있는 생성자 확인해 보기 , this 의 활용

 

* 매개변수가 있는 생성자만 만들어 놓게 되면 이런 오류가 발생된다.

The constructor Phone() is undefined 오류 발생.

 

매개변수가 있는 생성자를 만들때 꼭 기본생성자를 만들자.

public  Phone() {
		
}//기본 생성자 메서드

public  Phone(String company , int price) {
	company = company; // 구분이 가지 않는 상태가 되어버림. 
}// 매개변수 생성자 메서드

매개변수의 변수명과 , 인스턴스의 변수명이 같아버리면 , 

company = company 같은 사태가 발생된다.

이런 불편함을 위해 this 가 나타났다.

this.company = company;

this 는 현재의 인스턴스를 일컫는다. 그로인해 인스턴스 멤버 변수를 표기 할 수 있다.

두개의 인자를 전달받아 두개의 현재 인스턴스 멤버 변수를 초기화 할 수 있다.

public  Phone() {
		
}//기본 생성자 메서드

public  Phone(String company , int price) {
	//company = company; // 구분이 가지 않는 상태가 되어버림. 
    this.company = company; 
    // this 는 현재 인스턴스를 일컫는다. 
    //그로 인해 인스턴스 멤버 변수를 표기할 수 있다.
	this.price = price;
}// 매개변수 생성자 메서드

 

인자를 활용하여 , 변수값을 초기화 하는 용도로 사용한다.

기본생성자의 변수값 초기화와 , 매개변수 생성자를 통한 변수값 초기화를 비교해보자.

 

		//1.Default Constructor(= 기본생성자. 인자가 없는 생성자) 확인 
		Phone phone1 = new Phone(); // new(생성) , Phone() (생성자 메서드)
		phone1.company = "apple";
		phone1.number="010-0000-0000";
		phone1.price = 10000;
		System.out.println("phone1.toString() : "+phone1);
		
		//2.인자가 있는 생성자 확인
		Phone phone2 = new Phone("LG", 2000);
		System.out.println("phone1.toString() : "+phone2);

 

매개변수를 활용하여 생성자 함수를 사용한 경우가 굉장히 간결해지고 가독성도 올라간다.

 

이번에는 인자로 모든 변수를 초기화 하는 생성자를 만들어보자.

많이 사용하게 된다.

public Phone (String company ,String number , int price , int count) {
	this.company = company;
	this.number = number;
	this.price = price;
	Phone.count = count;
	System.out.println("test : 모든 인자의 count: "+count);
}
Phone phone3 = new Phone("LG","0000000", 2000);
System.out.println("phone3.toString() : "+phone3);

=====static 의 count의 접근방법 (this로 의미하면 안됨.)

Phone.count = count; // static 변수는 staic 하게 접근

 

 

this() 의 활용.
public Phone (String company ,String number , int price , int count) {
	this.company = company;
	this.number = number;
	this.price = price;
	Phone.count = count;
	System.out.println("test : 모든 인자의 count: "+count);
}

public Phone (String company  , String number) {
	this(company,number,0,0); // 인자가 일치하는 생성자 함수를 호출
	count++;
	System.out.println("test : this()활용 count: "+count);
}

 

인자를 2개를 던졌지만 this()를 사용함으로서 모든 항목의 인스턴스 변수를 초기화 하게 되었다.

Phone phone5 = new Phone("삼성","12345");
System.out.println("phone5.toString() : "+phone5);

 

결과를 보면 생성자 함수가 this()에 해당하는 함수를 호출한 후, 실행된다.

this()를 첫줄에 입력했으니 당연한 결과가 아닐까 ?