Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
JAVA/Java Intermediate(OOP)

4. 생성자 Construct

by Toughie 2024. 3. 2.

 

 

Swift를 공부하면서도 만났던 생성자. Java에서도 거의 유사했다.

다만 Swift에서는 Initializer였다면 Java에서는 Construct로 부른다는 것?

 

생성자는 말 그대로 객체를 생성하는데 도움을 주는 메서드이다.

정확히는 객체를 생성한 직후에 값 초기화를 할 수 있도록 하는 특별한 메서드이다.

 

public class Student {
    String name;
    int age;
    int grade;
}

 

위와 같은 클래스가 있다. 

Student student1 = new Student();

//멤버 변수 초기값 설정
student1.name = "user1";
student1.age = 20;
student1.grade = 90;

 

java는 객체를 생성해주고 초기화를 하지 않으면, 멤버의 타입에 맞게 자동으로 초기화 된다고 했다. 
(String 타입은 Null로, int는 0으로, boolean은 false로)

하지만 객체를 만들면 보통 내가 원하는 값들을 멤버에 채워서 사용하게 된다. (초기화를 직접 해준다.)

위와 같이 멤버에 하나하나 접근해서 설정해줄 수도 있지만, 객체가 많아지면 번거롭고 비효율적일 수 있다.

 

void initStudent(String name, int age, int grade) {
    this.name = name;
    this.age = age;
    this.grade = grade;
}

Student student2 = new Student();
student2.initStudent("student2",23,80);

 

위와 같은 메서드를 직접 구현해서 Student 클래스에 넣으면, 멤버 메서드로 편리하게 객체를 생성할 수 있다.

this ?

this는 해당 인스턴스, 즉 자신의 참조값을 표시해주는 것이다. '이 객체의'

 

최근에는 IDE의 발전으로 멤버가 색깔 등으로 구별이 잘 되지만, 확실하게 멤버임을 표기하기 위해 사용되는 키워드이다.

특히나 메서드에서 파라미터명과 멤버 변수명이 같은 경우에는 this를 써줘야 한다.

why? 멤버 변수보다 매개변수가 더 가까운 스코프에 있기 때문에 매개변수가 우선순위를 가지기 때문이다.

파라미터명과 멤버명이 같은 경우를 제외하면 this를 생략해주어도 무방하다.

 

바로 위 예시코드의 경우 결국 객체를 생성하고 초기화를 해주는 것에 2줄이 필요하다.

어차피 객체를 생성할 때마다 초기화를 해줄 거라면 생성할 때 바로 초기화 해주는 것이 편하지 않을까?

이를 위해 등장한 것이 바로 생성자이다.

(편의상 Swift에서 사용하는 용어들을 사용해서 생성자를 구분하려 한다. _ 기본, 지정, 편의)


기본 생성자

우리가 클래스의 객체를 생성할 때는 new 클래스이름(); 와 같이 작성해왔다.

사실 여기서 ()는 기본 생성자를 호출하는 것이다. (Swift에서는 .init()에서 .init을 생략한 것과 마찬가지)

Java는 개발자가 직접 생성자를 구현하지 않는 이상, 아무 파라미터도, 동작도 없는 깡통 기본 생성자를 자동으로 만들어 준다.

 

public class Student {
    String name;
    int age;
    int grade;
    
    //생성자의 이름은 클래스명과 반드시 동일해야한다.
    //아래와 동일한 기본 생성자를 Java가 만들어 준다.
    public Student() { }
}

 

단, 개발자가 직접 생성자를 하나라도 구현하는 경우에는 기본 생성자가 자동으로 생성되지 않는다.


지정 생성자

멤버들을 지정해서 초기화 해주는 생성자이다. 가장 보편적인 생성자일 것이다.

 

public class Student {
    String name;
    int age;
    int grade;
    
    //지정 생성자
    Student(String name, int age, int grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
}
//객체 생성 예시
Student student1 = new Student("student1", 20, 80);

 

위와 같이 지정 생성자를 구현한 경우, 객체 생성과 동시에 바로 지정생성자를 호출해서 초기화 까지 해줄 수 있다.

다만, 지정 생성자를 구현한 경우 '반드시 호출' 해줘야 한다. 즉 빈 괄호만 치면 컴파일 에러가 발생한다.

생성자를 직접 구현했다는 것은, 객체 생성에 대한 제약을 거는 것과 같다. 이 객체 만들려면 이런 값들이 필요해!!


편의 생성자

(Swift의 편의 생성자 개념을 차용, 생성자도 오버로딩이 가능하고 편리하게 서브 생성자를 구현할 수 있다고 이해해 주세요.)

생성자도 메서드이기 때문에 '오버로딩'이 가능하다.

클래스의 특정 멤버만 직접 초기화 해주고, 나머지는 기본값을 주고싶은 경우 등, 필요에 따라 생성자를 여러개 구현할 수 있다.

 

public class Student {
    String name;
    int age;
    int grade;
    //지정 생성자
    Student(String name, int age, int grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
    //생성자 오버로딩 _ 편의 생성자
    Student(String name, int age) {
        this(name, age, 50); //지정 생정자 호출 반드시 첫줄에 작성
//        this.name = name;
//        this.age = age;
//        this.grade = 50; //기본값 제공. 편의 생성자
    }
}

 

마지막 생성자를 보면 name, age만 받고 grade는 기본으로 50을 주겠다는 생성자인데,

중복되는 코드가 있기 때문에 '지정 생성자'를 호출하는 방식을 사용하고 있다.

이렇게 지정 생성자를 호출하는 방식으로 생성자를 오버로딩 하는 경우에는 

반드시 생성자 코드의 첫번째 줄에 this를 작성해줘야 한다. 아니면 컴파일 에러가 발생한다. 


command + p

 

이렇게 클래스에 대한 다양한 생성자를 활용해 객체 초기화의 여러 옵션을 제공할 수 있음을 알아보았다.

 


학습 출처

김영한의 실전 자바 - 기본편