본문 바로가기
Java/객체지향 프로그래밍 기초

5. 생성자(Constructor)

by mozzi329 2022. 7. 8.
728x90

 

     

     

    일반유닛 탱크 vs 영웅유닛 탱크

    📌 Goal

    • 생성자의 핵심 개념과 기본 문법을 이해하고 사용할 수 있다.
    • 생성자가 메서드와 구분되는 두 가지 차이를 이해하고 설명할 수 있다.
    • 메서드 오버로딩이 생성자에서 어떻게 구현될 수 있는 지 확인하고 이해할 수 있다.
    • 기본 생성자와 매개변수가 있는 생성자의 차이를 설명할 수 있다.
    • this 와 this() 의 차이에 대해 설명할 수 있다.

     

    📌 생성자(Constructor)

    객체를 생성하는 역할을 하는 클래스의 구성 요소로서, 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드

    new키워드를 사용하여 객체를 생성할 때에 호출되는 것이 사실 바로 이 생성자다. 그러나 생성자라는 이름에서 생성자가 인스턴스를 생성하는 역할을 하는 것은 아니다. 인스턴스 생성을 담당하는 것은 new키워드이며, 생성자는 인스턴스 변수들을 초기화하는 데 사용되는 특수한 메서드이다.

     

    ✔️ 생성자(Constructor)와 메서드(Method)의 차이

    생성자의 이름은 반드시 클래스의 이름과 같아야 한다.

    만약 클래스 이름과 생성자의 이름이 다르다면 그 메서드는 더이상 생성자로서의 기능을 수행할 수 없다.

     

    생성자는 리턴 타입이 없다.

    메서드에서 리턴 값이 없을 때 표시하는 void 키워드를 사용하지 않는다. 그 이유는 무언가를 ‘리턴하지 않는다’를 의미하는 void와는 다르게 생성자는 아예 리턴 타입 자체가 존재하지 않기 때문이다.

     

    클래스명(매개변수) { // 생성자 기본 구조
    	...생략...
    }
    

    먼저 클래스명과 같은 이름의 생성자명을 작성해주고 리턴 타입이 없기 때문에 리턴 타입에는 아무것도 적지 않는다. 매개변수는 있을 수도 있고 없을 수도 있다.

     

    ❗️ 기억해야할 점

    생성자도 메서드 오버로딩과 같이 오버로딩이 가능하므로 한 클래스 내에 여러 개의 생성자가 존재할 수 있다. 

    스타크래프트의 예를 들면 일반 유닛 탱크와 영웅 유닛 탱크의 예로 들어볼 수 있다. 동일한 탱크 클래스를 조건에 따라 생성자를 오버로딩해서 다형성을 줄 수 있다.

     

    public class ConstructorExample {
        public static void main(String[] args) {
            Tank tank1 = new Tank();
            Tank tank2 = new Tank("영웅유닛 탱크");
        }
    }
    
    class Tank {
        Tank() { // (1) 생성자 오버로딩
            System.out.println("일반유닛 탱크");
        }
    
        Tank(String str) { // (2)
            System.out.println("영웅유닛 탱크");
        }
    }
    

     

    📌 기본생성자(Default Constructor) vs 매개변수가 있는 생성자

    ✔️ 기본생성자(Default Constructor)

    기본 생성자(Default Constructor)는 매개변수가 없는 생성자를 의미한다.

    모든 클래스에는 반드시 하나 이상의 생성자가 존재해야 한다. 생성자를 따로 만들지 않아도 정상적으로 인스턴스를 만들 수 있는 이유는 만약 생성자가 클래스 안에 포함되어 있지 않은 경우에는 자바 컴파일러가 기본 생성자를 자동으로 추가해주기 때문이다. 만약에 생성자가 이미 추가되어있는 경우 기본생성자가 아니라 이미 추가되어 있는 생성자를 기본으로 사용한다.

     

    클래스명(){} //기본 생성자
    
    DefaultConst(){} // 예시) DefaultConst 클래스의 기본 생성자
    

     

    ✔️ 매개변수가 있는 생성자

    매개변수가 있는 생성자는 메서드처럼 매개변수를 통해 호출 시에 해당 값을 받아 인스턴스를 초기화하는 데 사용한다.

    고유한 특성을 가진 인스턴스를 계속 만들어야하는 경우 인스턴스마다 각기 다른 값을 가지고 초기화할 수 있어서 매우 유용하다.

     

    📌 this() vs this 키워드

    ✔️ this()

    this() 메서드는 자신이 속한 클래스에서 다른 생성자를 호출하는 경우에 사용한다.

    메서드의 호출에서 같은 클래스 안에 메서드들끼리 서로 호출할 수 있었던 것처럼 생성자도 tihs() 메서드를 통해 상호 호출이 가능하다.

    this()메서드를 사용하기 위해서 크게 두 가지의 문법요소를 충족해야한다.

    첫 째, this() 메서드는 반드시 생성자의 내부에서만 사용할 수 있다.

    둘 째, this() 메서드는 반드시 생성자의 첫 줄에 위치해야 한다.

     

    public class Test {
        public static void main(String[] args) {
            Example example = new Example();
            Example example2 = new Example(5);
        }
    }
    
    class Example  {
        public Example() {
            System.out.println("Example의 기본 생성자 호출!");
        };
    
        public Example(int x) {
            this();
            System.out.println("Example의 두 번째 생성자 호출!");
        }
    }
    
    //Output
    Example의 기본 생성자 호출!
    Example의 기본 생성자 호출!
    Example의 두 번째 생성자 호출!
    

     

    Example클래스는 두 개의 생성자를 가지고 있다. 하나는 매개변수가 필요하지 않은 기본 생성자이고, 다른 하나는 int 타입의 매개변수를 받고 있는 생성자이다. 그리고 두 번째 생성자 내부의 첫 번째 줄에 this() 메서드가 포함되어 있다.

     

    이제 Example클래스를 기반으로 만들어지는 인스턴스를 생성하면, 첫 번째 생성자가 호출되고 그 결과로 Example의 기본 생성자 호출!이라는 문구가 출력된다. 다음으로 두 번째 생성자를 사용하여 객체를 만드는 과정에서 생성자가 호출되면 먼저 this()메서드가 출력되어 다시 첫 번째 기본생성자가 호출되고, 그 다음으로 Example의 두 번째 생성자 호출!이라는 문구가 출력된다.

     

    ✔️ this 키워드

    this 키워드는 변수를 구분해주기 위한 용도로 사용된다. 

    인스턴스 변수와 매개변수를 이름만으로는 구분하기가 어려워지는 문제가 발생하게 되는데 이를 해결하기 위해 this 키워드를 사용한다.

     

    public class ConstructorExample {
        public static void main(String[] args) {
            Car car = new Car("Model X", "빨간색", 250);
            System.out.println("제 차는 " + car.getModelName() + "이고, 컬러는 " +  car.getColor() + "입니다.");
        }
    }
    
    class Car {
        private String modelName;
        private String color;
        private int maxSpeed;
    
        public Car(String modelName, String color, int maxSpeed) {
            this.modelName = modelName;
            this.color = color;
            this.maxSpeed = maxSpeed;
        }
    
        public String getModelName() {
            return modelName;
        }
    
        public String getColor() {
            return color;
        }
    }
    
    //Output
    제 차는 Model X이고, 컬러는 빨간색입니다.
    

     

    인스턴스 변수로 modelName, color, 그리고 maxSpeed가 선언되어 있는데, 동시에 생성자의 매개변수로 modelName, color, maxSpeed가 정의되어 있다. 만약에 위의 코드에서, this.modelName = modelName 대신 modelName = modelName라고 작성하면 둘 다 지역변수로 간주되고 만다. 이때, 이 변수들의 구분을 해주기 위한 용도로 주로 사용되는 방법이 바로 this 키워드이다.

     

    this는 인스턴스 자신을 가리키며, 우리가 참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼 this를 통해서 인스턴스 자신의 변수에 접근할 수 있다. 예를 들면, 현재 Car클래스의 modelName이라는 인스턴스 필드를 클래스 내부에 출력하고자 한다면 원래는 System.out.println(this.modelName)이런 방식으로 작성해주어야 한다.

    댓글