본문 바로가기
IT/김영한의실전JAVA-기본_inFlearn

4. 생성자 - 생성자가 필요한 이유 / this / 생성자(도입) / 기본 생성자 / 생성자(오버로딩과 this() ) / 문제와 풀이

by for-learn 2025. 2. 8.

4-1. 생성자 - 필요한 이유

객체를 생성하는 시점어떤 작업을 하고 싶다면 생성자(Construct)를 이용

 

MemberInit.java (클래스)

package construct;

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

MethodInitMain1.java

package construct;

public class MethodInitMain1 {
    public static void main(String[] args) {
        MemberInit member1 = new MemberInit();
        member1.name = "user1";
        member1.age = 15;
        member1.grade = 90;

        MemberInit member2 = new MemberInit();
        member2.name = "user2";
        member2.age = 16;
        member2.grade = 80;
        
        MemberInit[] members = {member1, member2};

        for (MemberInit s : members) {
            System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
        }
    }
}
  • 회원 객체를 제대로 사용하기 위해서는, 객체를 생성하자 마자 name, age, grade 초기값을 설정해야 함.
  • 회원의 초기값 설정하는 반복코드를 메서드를 사용해 제거할 예정

MethodInitMain2.java (반복 코드를 메서드로)

package construct;

public class MethodInitMain2 {
    public static void main(String[] args) {
        MemberInit member1 = new MemberInit();
        initMember(member1, "user1", 15, 90);
        
        MemberInit member2 = new MemberInit();
        initMember(member2, "user2", 16, 80);

        MemberInit[] members = {member1, member2};

        for (MemberInit s : members) {
            System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
        }
    }

    static void initMember(MemberInit member, String name, int age, int grade) {
        member.name = name;
        member.age = age;
        member.grade = grade;
    }
}
  • initMember(...) 메서드를 사용해서 반복을 제거
  • initMember(...)  메서드는 대부분 MemberInit 객체의 멤버 변수를 사용
    => MemberInit이 자신의 데이터를 변경하는 기능(메서드)을 제공하는 것이 좋음. (속성과 기능을 한 곳에)

 

4-2. this

MemberInit.java (initMember( ) 추가)

package construct;

public class MemberInit {
    String name;
    int age;
    int grade;

    // 추가
    void initMember(String name, int age, int grade) {
        this.name = name; // 멤버 변수와 매개 변수의 이름이 같을 때 가까운 순으로 우선순위를 가진다.
        this.age = age; // this는 인스턴스 자신(참조값)을 가리키기 때문에
        this.grade = grade; // this.grade 는 x001.grade 가 된다.
    }
}

MethodInitMain3.java

package construct;

public class MethodInitMain3 {
    public static void main(String[] args) {
        MemberInit member1 = new MemberInit();
        member1.initMember("user1", 15, 90);

        MemberInit member2 = new MemberInit();
        member2.initMember("user2", 16, 80);

        MemberInit[] members = {member1, member2};

        for (MemberInit s : members) {
            System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
        }
    }
}
  • 메서드를 호출하면 객체의 멤버 변수에 인자로 넘어온 값을 채운다.
    => member1.initMember("user1", 15, 90)

this

멤버 변수와 메서드의 매개변수의 이름이 같을 때,

  • 멤버 변수보다 매개변수가 코드 블럭의 더 안쪽에 있기에 매개변수가 우선순위를 가진다. 
    => initMember (String name,...) 메서드 안에서 name이라고 적으면 매개변수에 접근
  • 멤버 변수에 접근하려면 앞에 this.를 기입 => this인스턴스 자신의 참조값을 가리킴.

MethodInitMain3.java (this의 생략)

package construct;

public class MemberThis {
    String nameField;

    void initMember(String nameParameter) {
        nameField = nameParameter; // nameField는 매개변수로 사용이 되지 않았기에 this 생량
    }
}
  • nameFieldinitMember(...) 메서드 매개변수의 이름과 같지 않아 멤버 변수로 우선순위가 넘어가므로 생략 가능

 

4-3. 생성자 - 도입

생성자를 사용하면 객체를 생성하는 시점에 즉시 필요한 기능을 수행

MemberConstruct.java (생성자)

package construct;

public class MemberConstruct {
    String name;
    int age;
    int grade;

    MemberConstruct(String name, int age, int grade) {
        System.out.println("생성자 호출 name=" + name + ", age=" + age + ", grade=" + grade);
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
}

생성자메서드 차이

  • 생성자의 이름클래스 이름과 같음 (생성자명 = 클래스명). 따라서 첫 글자도 대문자로 시작
  • 생성자는 반환 타입이 없다. 비워두어야 한다.
  • 나머지는 메서드와 같다.

ConstructMain1.java (생성자)

package construct;

public class ConstructMain1 {
    public static void main(String[] args) {
        MemberConstruct member1 = new MemberConstruct("user1", 15, 90);
        // Ctrl+P 어떤 파라미터가 필요한지 확인하는 단축키
        // 객체를 생성하는 동시에 생성자를 호출함.
        MemberConstruct member2 = new MemberConstruct("user2", 16, 80);

        MemberConstruct[] members = {member1, member2};

        for (MemberConstruct s : members) {
            System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
        }
    }
}
  • Ctrl+P: 어떤 파라미터가 필요한지 확인하는 단축키

 

생성자 호출

생성자는 인스턴스를 생성하고 즉시 호출됨.

호출 방법 => new 명령어 다음에 생성자 이름매개변수에 맞는 인수를 전달

new 생성자이름(생성자에 맞는 인수 목록)
new 클래스이름(생성자에 맞는 인수 목록)
// 생성자이름 = 클래스이름

 

생성자 장점 => 중복 호출 제거

// 생성자 등장 전
MemberInit member = new MemberInit();
member.initMember("user1", 15, 90);
// 생성자 등장 후
MemberConstruct member = new MemberConstruct("user1", 15, 90);

 

제약(혹은 장점) => 생성자 호출 필수

생성자를 사용하지 않을 때는 initMemer(..) 메서드를 호출하지 않아도 프로그램은 작동한다.

하지만 회원의 이름, 나이, 성적 데이터가 없는 상태로 동작하기 때문에 추후 시스템에 문제가 발생할 수 있다. 

 

생성자를 사용하면, 객체를 생성할 때 직접 정의한 생성자가 있다면 직접 정의한 생성자를 반드시 호출해야 한다. 

생성자를 메서드 오버로딩처럼 여러개 정의할 수 있는데, 그 중 하나만 호출하면 된다. 

 

직접 정의한 생성자를 호출하지 않으면 컴파일 오류가 발생해, 정보가 없는 유령회원의 등장을 원천 차단

좋은 프로그램은 무한한 자유도가 주어지는 프로그램이 아니라 적절한 제약이 있는 프로그램

 

4-4. 기본 생성자

생성자를 만들지 않았는데, 생성자를 호출했었다.

MemberInit member1 = new MemberInit();

 

기본 생성자

  • 매개변수가 없는 생성자
  • 클래스에 생성자가 하나도 없으면 자바 컴파일러는 매개변수가 없고, 작동하는 코드가 없는 기본 생성자를 자동 생성
  • 생성자가 하나라도 있으면 자바는 기본 생성자를 만들지 않음
public class MemberInit {
    String name;
    int age;
    int grade;
 
    public MemberInit() { // 이와 같은 기본 생성자가 자동으로 생성
    } 
}

MemberDefault.java

package construct;

public class MemberDefault {
    String name;

    // 기본 생성자
//    public MemberDefault() { } 
    
    MemberDefault() {
        System.out.println("생성자 호출");
    }
}

자바가 자동으로 생성해주는 기본 생성자는 클래스와 같은 접근 제어자를 가진다. ex) public

MemberDefaultMain.java

package construct;

public class MemberDefaultMain {
    public static void main(String[] args) {
        MemberDefault memberDefault = new MemberDefault();
    }
}

 

기본 생성자를 자동으로 만드는 이유

  • 생성자는 반드시 호출되어야 하는데,
  • 기본 생성자 자동 생성이 없으면,
  • 생성자 기능이 필요하지 않은 경우에도 모든 클래스에 개발자가 직접 기본 생성자를 정의해야 함.

4-5. 생성자 - 오버로딩과 this( )

MemberConstruct.java (생성자 추가)

package construct;

public class MemberConstruct {
    String name;
    int age;
    int grade;

    // 추가
    MemberConstruct(String name, int age) {
        this.name = name;
        this.age = age;
        this.grade = 50;
    }

    MemberConstruct(String name, int age, int grade) {
        System.out.println("생성자 호출 name=" + name + ", age=" + age + ", grade=" + grade);
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
}

ConstructMain2.java

package construct;

public class ConstructMain2 {
    public static void main(String[] args) {
        MemberConstruct member1 = new MemberConstruct("user1", 15, 90);
        MemberConstruct member2 = new MemberConstruct("user2", 16);

        MemberConstruct[] members = {member1, member2};

        for (MemberConstruct s : members) {
            System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
        }
    }
}

 

this( )

생성자에서 중복되는 코드를 수정

this.name = name;
this.age = age;

MemberConstruct.java (this( ) 사용)

package construct;

public class MemberConstruct {
    String name;
    int age;
    int grade;

    // 추가 1
/*
    MemberConstruct(String name, int age) {
        this.name = name;
        this.age = age;
        this.grade = 50;
    }
*/
    // 추가 2 - this()
    MemberConstruct(String name, int age) {
//      System.out.println("hello"); // this()는 생성자 코드 첫줄에 입력해야함.
        this(name, age, 50); // 변경
    }

    MemberConstruct(String name, int age, int grade) {
        System.out.println("생성자 호출 name=" + name + ", age=" + age + ", grade=" + grade);
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
}
  • this( )를 사용하면 생성자 내부에서 다른 생성자를 호출
  • this는 인스턴스 자신의 참조값을 가리킴 => 자신의 생성자를 호출한다. 

this( ) 규칙

  • this( )는 생성자 코드의 첫줄에만 작성 가능
  • 아니면, 컴파일 오류가 발생

 

4-6. 문제와 풀이

Book.java

package construct.ex;

public class Book {
    String title; // 제목
    String author; // 저자
    int page; // 쪽 수

    Book(){
        this("", "", 0); // => 놓침
    }

    Book(String title, String author) {
        this.title = title;
        this.author = author;

        // or this(title, author, 0);
    }

    Book(String title, String author, int page) {
        this.title = title;
        this.author = author;
        this.page = page;
    }

    void displayInfo() {
        System.out.println("제목: "+title+", 저자: "+author+", 페이지: "+page);
    }
}

 

※ 생성자는 객체 생성 직후 객체를 초기화 하기 위한 특별한 메서드