JAVA 생성자

Dev.Shinny·2022년 9월 22일
0

자바의 정석

목록 보기
4/18

생성자란?

인스턴스가 생성될 때, 호출되는 '인스턴스 초기화 메서드'이다.

인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.

생성자 역시 메서드처럼 클래스 내에 선언되며, 구조도 메서드와 유사하지만 리턴값이 없으며 void를 적지 않는다.

  1. 생정자의 이름은 클래스의 이름과 같아야 한다.
  2. 생성자는 리턴 값이 없다.

생성자도 오버로딩이 가능하고, 하나의 클래스에 여러개의 생성자가 존재할 수 있다.

클래스명(타입 변수명, 타입 변수명, ...){
	//인스턴스 생성 시 수행될 코드.
    //주로 인스턴스 변수의 초기화 코드를 적는다.
}

class Card(){
	
	Card(){ 
    ...
    }
    Card(String K, int num){
    ...
    }
    ...
}

연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것은 아니다!

Card card1 = new Card();
  1. 연산자 new에 의해서 메모리(heap)에 Card 클래스의 인스턴스가 생성된다.
  2. 생성자 Card()가 호출되어 수행된다.
  3. 연산자 new의 결과로, 생성된 Card인스턴스의 주소가 반환되어 참조변수 c에 저장된다.

기본 생정자(default constructor)

모든 클래스에는 반드시 하나 이상의 생성자가 정의되어 있어야 한다. 지금까지 생성자를 정의하지 않고도 인스턴스 생성이 가능했던 이유는 컴파일러가 제공하는 '기본 생성자(default constructor)'덕분이었다.

클래스명() {} 
Card() {}

컴파일러가 자동적으로 추가해주는 기본 생성자는 매개변수도 없고 아무런 내용도 없는 아주 간단한 것이다. 특별히 인스턴스 초기화 작업이 요구되지 않는다면 생성자를 따로 정의하지 않고 기본 생성자를 사용하는 것도 좋다.

class Data1{
	int value;
}

class Data2{
	int value;
    
    Data2 (int x){
    	value=x;
    }
}

class ConstructorTest{
	public static void main(String[] args){
  	Data1 d1 = new Data1();
    Data2 d2 = new Data2(); // 컴파일 에러
    // Data2 d2 = new Data2(10); 에러 x 
  }
}

Data1에는 정의되어 있는 생성자가 하나도 없으므로 컴파일러가 기본 생성자를 추가해주지만, Data2는 이미 생성자 Data2 (int x)가 정의되어 있어 기본생성자가 추가되지 않았다.

컴파일러가 자동적으로 기본 생성자를 추가해주는 경우는 '클래스 내에 생성자가 하나도 없을 때'뿐이다.

매개변수가 있는 생성자

생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화 작업에 사용할 수 있다. 인스턴스마다 각기 다른 값으로 초기화되어야 하는 경우가 많기 때문에 매개변수를 사용한 초기화는 매우 유용하다.

class Car {
	String color;
    String gearType;
	int door;
    
    Car(){} // 기본 생성자
    Car(String c, String g, int d){
    	color=c;
        gearType = g;
        door =d;
    }
}

위 코드처럼 Car(String color, String gear, int door)를 사용한다면, 인스턴스를 생성하는 동시에 원하는 값으로 초기화 할 수 있다.

(1)
Car c = new Car ();
c.color = "green";
c.gearType = "auto";
c.door = 4;

(2)
Car c = new Car ("white", "auto",4);

(1)과 (2)는 모두 같은 내용이지만, (2) 코드가 더 간결하고 직관적이다.

생성자에서 다른 생성자 호출하기 - this(), this

같은 클래스의 멤버들 간 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다. 단 아래의 조건을 만족시켜야 한다.

  • 생성자의 이름으로 클래스이름 대신 this를 사용한다.
  • 한 생성자에서 다른 생성자를 호출할 떄는 반드시 첫 줄에서만 호출이 가능하다.

생성자에서 다른 생성자를 첫 줄에서만 호출이 가능하도록 한 이유는 생성자 내에서 초기화 작업도충에 다른 생성자를 호출하게 되면, 호출된 다른 생성자 내에서도 멤버변수들의 값을 초기화 할 것 이므로 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질 수 있기 때문이다.

class Car {
	String color;
    String gearType;
    int door;
    
    Car(){
    	this("white", "auto", 4);
        //Car(String color, String gearType, int door)를 호출
    }
    Car(String color){
    	this(color,"auto", 4);
    }
    Car(String color, String gearType, int door){
    	this.color = color;
        this.gearType = gearType;
        this.door = door;
    }
}

class CarTest {
	public static void main(String[] args){
    	Car c1 = new Car();
        Car c2 = new Car("blue");
        
        System.out.println(c1.color+", "+c1.gearType+", "+c1.door);
        System.out.println(c2.color+", "+c2.gearType+", "+c2.door);
    }
}

결과


생성자 Car()에서 또 다른 생성자 Car(String color, String gearType, int door)를 호출하였다. 이처럼 생성자간의 호출에는 생정자 이름 대신 this를 사용해야만 하므로 'Car'대신 'this'를 사용했다. 생성자 Car()의 첫째 줄에서 호출했다.

this를 사용해 인스턴스 변수와 매개변수로 선언된 지역변수를 구별할 수 있다. this.color는 인스턴스 변수이고, color는 생성자의 매개변수로 정의된 지역변수로 서로 구별 가능하다.

'this'는 참조변수로 인스턴스 자신을 가리킨다. 참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼, 'this'로 인스턴스변수에 접근할 수 있는 것이다.

사실 생성자를 포함한 모든 인스턴스메서드에는 자신이 관련된 인스턴스를 가리키는 참조변수 'this'가 지역변수로 숨겨진 채 존재한다.

this 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다.
this(), this(매개변수) 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.

this와 this()는 비슷하게 생겼을 뿐 완전히 다른 것이다. this는 '참조 변수'이고 this()는 생성자이다.

생성자를 이용한 인스턴스 복사

현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다. 두 인스턴스가 같은 상태를 갖는다는 것은 두 인스턴스의 모든 인스턴스 변수가 동일한 값을 갖고 있다는 것이다.

하나의 클래스로부터 생성된 모든 인스턴스의 메서드와 클래스 변수는 서로 동일하기 때문에 인스턴스간 차이는, 인스턴스마다 각기 다른 값을 가질 수 있는 인스턴스 변수 뿐이다.

    	Car c1 = new Car();
        Car c2 = new Car(c1); //c1의 복사본 c2를 생성한다.

인스턴스 c2는 c1을 복사하여 생성된 것이므로 서로 같은 상태를 갖지만, 서로 독립적으로 메모리공간에 존재하는 별도의 인스턴스이므로 c1의 값들이 변경되어도 c2는 영향을 받지 않는다.

인스턴스 생성시 결정할 2가지 사항

  1. 클래스 : 어떤 클래스의 인스턴스를 생성할 것인가?
  2. 생성자 : 선택한 클래스이 어떤 생성자로 인스턴스를 생성할 것인가?








< 출처 : 자바의 정석 >

profile
Hello I'm Shinny. A developer who try to enjoy the challenge.

0개의 댓글