Java

[Java] 생성자와 초기화

sujin7837 2022. 2. 18. 15:47
반응형

생성자와 초기화

생성자의 개념

생성자(constructor)는 클래스로부터 객체를 생성할 때 멤버 필드의 값을 초기화하는 등 기본적인 처리를 수행합니다.

 

생성자의 정의

생성자를 정의하는 방법은 메소드를 정의하는 방법과 유사하지만 몇 가지 다른점이 존재합니다.

첫째, 생성자의 이름은 반드시 클래스의 이름과 같아야 합니다.

둘째, 생성자는 메소드가 아니므로 리턴 타입이 없어야 하며, void로 선언될 수도 없습니다.

class A {
	public A() {...}	// 생성자
    public void A(int i) {}	// 생성자가 아님
}

셋째, 클래스를 상속하면 메소드는 자동으로 상속되지만 생성자는 상속이 되지 않습니다. 생성자를 지정하지 않으면 매개변수를 갖지 않은 생성자가 자동으로 생성되는데, 이를 디폴드 생성자(default constructor)라고 합니다. 디폴트 생성자는 클래스에 다른 생성자를 정의하지 않았을 때에만 자동으로 만들어지며, 생성자를 하나라도 정의하면 만들어지지 않습니다.

넷째, 클래스를 상속받은 경우 하위 클래스에서 상위 클래스의 생성자를 호출하기 위해서는 super() 메소드를 사용합니다. 이때, 상위 클래스의 생성자가 오버로딩이 된 경우에는 하위 클래스에서 super() 메소드를 호출할 때 매개변수의 개수와 매개변수의 데이터 타입에 따라 적합한 생성자가 호출됩니다.

※하위 클래스의 생성자에서 super() 메소드를 호출할 경우, super() 문장이 가장 먼저 기술되어야 합니다.※

 

클래스에서 디폴트 생성자 외에 매개변수를 갖는 생성자를 생성한 경우에는 디폴트 생성자가 생성되지 않으므로, 이 클래스가 하위 클래스로 상속될 가능성이 있는 경우에는 디폴트 생성자를 만들어두는 것이 좋습니다.

public class A {
	public A() {}	// 반드시 필요
    public A(int i) {}
}

class B extends A {
	public B() {
    	super();	//  상위 클래스의 생성자를 호출
    }
}

public static void main(String[] args) {
	B b=new B();
}

 

생성자의 오버로딩

생성자는 다른 메소드들과는 달리 자동으로 상속되지 않지만, 상위 클래스에 정의된 생성자를 오버로딩하는 것은 가능합니다. 클래스의 생성자를 호출할 경우, 호출된 생성자가 this() 메소드를 이용하여 다른 생성자를 다시 호출하도록 하는 것입니다.

public class A {
	String name;
    int score;
    
    public A(String name, int score) {	// 생성자 1
    	this.name=name;
        this.score=score;
    }
    
    public A(String name) {	// 생성자 2 : 생성자 1을 호출합니다.
    	this(name, 60);
    }
    
    public A() {	// 생성자 3 : 생성자 2를 호출하고, 생성자 2는 다시 생성자 1을 호출합니다.
    	this("unknown");
    }
}

 

생성자 호출 순서

상위 클래스를 상속한 하위 클래스의 인스턴스를 생성하면,

1) 상위 클래스의 생성자를 먼저 호출

2) 하위 클래스의 생성자를 실행

    2-1) super() 메서드를 호출한 경우, 해당하는 상위 클래스의 생성자가 실행됩니다.

    2-2) super() 메서드를 호출하지 않은 경우, 디폴트 생성자가 실행됩니다.

class FruitInfo {
	String color;
    FruitInfo() {
    	System.out.println("과일입니다.");
    }
    FruitInfo(String color) {
    	this.color=color;
        System.out.println(color+" 과일입니다.");
    }
}

public class Peach extends FruitInfo {
	public Peach() {
    	System.out.println("복숭아 입니다.");
    }
    
    public static void main(String[] args) {
    	Peach f=new Peach();
    }
}
// 결과 화면
과일입니다.
복숭아 입니다.

 

class FruitInfo {
	String color;
    FruitInfo() {
    	System.out.println("과일입니다.");
    }
    FruitInfo(String color) {
    	this.color=color;
        System.out.println(color+" 과일입니다.");
    }
}

public class Peach extends FruitInfo {
	public Peach(String color) {
    	super(color);
    	System.out.println("복숭아 입니다.");
    }
    
    public static void main(String[] args) {
    	Peach f=new Peach("분홍색");
    }
}
// 결과 화면
분홍색 과일입니다.
복숭아 입니다.

 

생성자와 객체 생성

다른 객체가 생성자를 호출하지 못하게 하지 위해서 생성자를 protected나 private으로 선언할 수도 있습니다. 그런데 private으로 선언하는 경우에는 외부의 어떤 객체도 생성자를 호출할 수 없어서 이 클래스를 이용하여 객체를 생성하지 못하는 문제가 발생합니다. 따라서 이 경우에 특정한 처리를 통하여 객체를 생성시키는 등의 방법을 제공해야 합니다.

 

생성자는 특정 클래스에 대해 new를 지정하여 객체를 생성할 때 자동으로 수행되는 것으로서, 객체 생성 과정은 다음 세 단계로 이루어집니다.

1) 객체를 위한 메모리가 할당되고, 디폴트 값으로 초기화 (null, 0 등)

2) 멤버 필드의 값 등을 초기화

3) 생성자가 구동됨

 

생성자는 멤버 필드의 값이 초기화 된 이후에 실행되기 때문에 궁극적으로 멤버 필드의 값을 설정하는 것은 생성자에서 수행하는 것이 바람직합니다. 특히, 객체에 고유한 id를 배정하는 작업은 생성자에서 담당하는 것이 안전합니다.

class InstantClass {
	int x=10;
    public InstantClass(int x) {
    	this.x=x;
    }
    public void m() {
    	System.out.println("x="+x);
    }
}

public class InstantMessage {
	public static void main(String[] args) {
    	new InstantClass(3).m();
    }
}
// 결과 화면
3

 

반응형