본문 바로가기
JAVA BASE/OOP(객체지향 프로그래밍)

04. [자바] 생성자(constructor)

by staticClass 2020. 12. 11.

생성자(constructor)란?

생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'이며
보통 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행될 작업을 위해서도 사용된다.
생성자 역시 메서드처럼 클래스 내에 선언되고 구조 또한 메서드와 유사하지만
리턴 값이 없다

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

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

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

class Card {
    Card() {    // 매개변수가 없는 생성자
        ···
    }

    Card(String k, int num) {    // 매개변수가 있는 생성자
        ···
    }
}

연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것이 아니다.
수행되는 과정을 단계별로 나누면

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

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

기본 생성자(default constructor)

기본 생성자가 컴파일러에 의해서 추가되는 경우는
클래스에 정의된 생성자가 하나도 없을 때 뿐이다.

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

위의 에러는 Data2 클래스에서 생성자를 찾을 수 없다는 내용인데

Data1의 경우 생성자가 하나도 없어서 기본 생성자가 만들어져 문제가 없지만

Data2의 경우는 이미 생성자가 존재하기 때문에 기본 생성자가 만들어지지 않기 때문에

컴파일 에러가 발생한다.

자동적으로 기본 생성자가 추가되는 경우는 '클래스 내에 생성자가 하나도 없을 때'

이기 때문이다

위의 코드에서 에러를 없애기 위해서는 인스턴스를 생성할 때 매개변수를 사용해

Data2(int x) 생성자를 사용하던가 추가로 생성자 Data2()를 정의해주어야 한다.

인스턴스를 생성한 다음 인스턴스변수의 값을 변경하는 것보다 매개변수를 갖는 생성자를 사용하는 것이
코드를 보다 간결하고 직관적으로 만든다.

Card c = new Card();    // 생성자의 매개변수를 사용하지 않을 때
c.color = "red";
c.type = "heart"
c.number = 7;
    ↓
Card c = new Card("red", "heart", 7); // 생성자의 매개변수로 멤버변수들을 초기화.

위의 코드는 모두 같은 내용이지만, 아래의 한 줄로 된 코드가 더 간결하고 직관적이다.
클래스를 작성할 때 다양한 생성자로 인스턴스 생성 후 별도로 초기화를 하지 않아도 되도록
하는 것이 바람직하다.

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

같은 클래스의 멤버들 간에 서로 호출이 가능하듯이 생성자 간에도 서로 호출이 가능하다

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

this : 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다.
       모든 인스턴스메서드에 지역변수로 숨겨진 채로 존재한다.
this(), this(매개변수) : 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.

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

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

Car(Car c){    // 매개변수로 인스턴스의 주소를 넘겨받음
    color     = c.color;        // 매개변수로 받은 인스턴스의 주소에 있는 color변수의 값
    gearType = c.gearType;  // 매개변수로 받은 인스턴스의 주소에 있는 gearType변수의 값
    door     = c.door;        // 매개변수로 받은 인스턴스의 주소에 있는 door변수의 값
}

 


 

여태까지 내가 해왔던 코딩이 얼마나 객체지향적이지 않았는지 느끼고 있다.
생성자는 물론이고 오버로딩도 사용하지 않으며 코딩해왔으니 말이다.
위기감을 느끼고 가능한 모든걸 활용하려는 습관을 들여야겠다.🤦‍♂️

댓글