JAVA

[Java] 생성자

songsua 2024. 10. 23. 23:03

대부분의 객체 지향 언어는 객체를 생성하자마자 즉시 필요한 기능을 좀 . 더편리하게 수행할 . 수있도록 생성자라는 기능을 제공한다.

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

 

기존 코드를 유지하기 위해 MemberConst 라는 새로운 클래스를 작성하였다.

 

package construct;

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

 

생성자는 메서드와 비슷하지만,

  • 생성자의 이름은 클래스이름과 같다. 따라서 첫 글자도 대문자로 시작한다.
  • 생성자는 반환 타입이 없다. 비워놔야한다.
  • 나머지는 메서드랑 같다.
package construct;

public class MemberconMain1 {
    public static void main(String[] args) {

        MemberCon member1 = new MemberCon("user1", 16, 90);
        MemberCon member2 = new MemberCon("user2", 20, 50);

        MemberCon[] members = {member1, member2};
        for (MemberCon s : members) {
            System.out.println("생성자 호출 =" + s.name + " age" + s.age + " grade" + s.grede);
        }

    }
}

 () : 괄호를 포함해야하는 이유는 생성자 때문이다. 객체를 생성하면서 동시에 생성자를 호출한다는 의미를 포함한다.

지금까지 new 키워드를 사용하면서 객체를 생성할 때마다 ()을 사용했던 이유는 바로 "생성자" 때문이다.

객체를 생성하면서 동시에 "생성자" 를 호출해야한다는 의미를 포함한다.

 

그렇다면 생성자의 장점은 

 

  • 중복 호출을 제거
    메서드를 한번 . 더호출해야 했다. 하지만 생성자를 생성하면 동시에 생성하고 작업을 줄이는 효과가 있다.
    생성자 등장 전,
Construct01 member2 = new Construct01();
initMember(member2, "user2", 22, 87);

//static 메서드는 main 메서드 밖에서 정의 해야함
    static void initMember(Construct01 member, String name, int age, int grade) {
            member.name = name;
            member.age = age;
            member.grade = grade;

 

생성자 등장 후,

MemberCon member1 = new MemberCon("user1", 16, 90);

 

  • 제약- 호출 필수
    메서드에서 실수로 호출을 빼먹으면 프로그램을 작동한다.
    하지만 생성자는 오류가 생긴다.

    메서드의 경우
Construct01 member1 = new Construct01();
initMember(member1, "yun", 14, 90);

Construct01 member2 = new Construct01();
//initMember(member2, "user2", 22, 87);

하나를 빠져도 제대로 들어간다.

 

생성자의 경우

package construct;

public class MemberconMain1 {
    public static void main(String[] args) {

      // MemberCon member1 = new MemberCon("user1", 16, 90);
       MemberCon member2 = new MemberCon("user2", 20, 50);

        MemberCon[] members = {member1, member2};
        for (MemberCon s : members) {
            System.out.println("생성자 호출 =" + s.name + " age" + s.age + " grade" + s.grede);

        }

    }
}
java: cannot find symbol
  symbol:   variable member1
  location: class construct.MemberconMain1

라는 오류가 생성된다.

package construct;

public class MemberconMain1 {
    public static void main(String[] args) {

       /MemberCon member1 = new MemberCon(/*"user1", 16, 90*/);
        MemberCon member2 = new MemberCon("user2", 20, 50);

        MemberCon[] members = {member1, member2};
        for (MemberCon s : members) {
            System.out.println("생성자 호출 =" + s.name + " age" + s.age + " grade" + s.grede);

        }

    }
}

 

의 경우에도 오류가 뜬다.

 

생성자를 사용하면 필수값 입력을 보장할 수 있다.

 

생성자는 반드시 호출되어야 한다.

생성자가 없으면 기본 생성자가 제공된다.

생성자가 하나라도 있으면 기본 생성자가 제공되지 않는다. 이런 경우에는 개발자가 직접 호출해야한다.

 

 

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

package construct;

public class MemberCon {
        String name;
        int age;
        int grede;

        //생성자 추가
        MemberCon(String name, int age) {
            this.name = name;
            this.age = age;
            this.grade = 50;   //이름과 나이가 있으면 성적은 50점부터 시작한다,
        }
        
        MemberCon(String name, int age, int grade) {
            System.out.println("생성자 호출 name =" + name + ", age =" + age + ", grade =" + grade);
            this.name = name;
            this.age = age;
            this.grede = grade;

        }
}

 

기존에 있던 생성자와 해서 두개가 생성되었다. 이를 오버로딩이라고 한다.

MemberCon {
        String name;
        int age;
        int grede;

        //생성자 추가
        MemberCon(String name, int age) {
            this.name = name;
            this.age = age;
            this.grade = 50; 

새로 생성된 생성자는 grade 를 안받으나, this grade = 50 을 통해 50점을 받는다.

 

package construct;

public class MemberconMain2 {
    public static void main(String[] args) {

       MemberCon member1 = new MemberCon("user1", 16, 90);
        MemberCon member2 = new MemberCon("user2", 20);

        MemberCon[] members = {member1, member2};
        for (MemberCon s : members) {
            System.out.println("생성자 호출 =" + s.name + " age" + s.age + " grade" + s.grade);
        }

    }
}

 

생성자 호출 name =user1, age =16, grade =90
생성자 호출 =user1 age16 grade90
생성자 호출 =user2 age20 grade50

 

grade 를 안적을 경우 위의 생성자에서 적용한 50 점이  호출되게 된다.

 

this()

두 생성자를 비교해 보면 코드가 중복되는 부분이 있다.

package construct;

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

        //생성자 추가
        MemberCon(String name, int age) {
            this.name = name;
            this.age = age;
            this.grade = 50;   //이름과 나이가 있으면 성적은 50점부터 시작한다,
        }

        MemberCon(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.name, this.age, this.grade  부분이 중복이 된다.

이 중복을 제거하기 위해서는 

package construct;

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

        //생성자 추가
        MemberCon(String name, int age) {
            this(name, age, 50);
        }

        MemberCon(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(name, age, 50); 처럼 점수 항족 50을 넣고 시작할 한다.
메인에서

MemberConstruct memeber1 = new MemberConstruct("user1", 15, 90);
MemberConstruct memeber2 = new MemberConstruct("user2", 18);

할 경우에 

user1 15 90
user2 18 50

로  출력된다.
        

문제풀이1

//BookMain 코드가 작동하도록 Book 클래스를 완성하세요
//특히 Book클래스의 생성자 코드에 중복이 없도록 주의하시오

 

package construct;

public class BookMain {
    public static void main(String[] args) {
        //기존 생성자 사용 Book()가 전용으로 사용할 수 있는 생성자가 필요하다.
        Book book1 = new Book();
        book1.displayinfo();

        //title과 author 만을 매개변수로 받는 생성자
        Book book2 = new Book("Hello", "song");
        book2.displayinfo();

        Book book3 = new Book("Hi", "yun", 10);
        book3.displayinfo();
    }
}
package construct;

public class Book {
    String title;
    String author;
    int page;
    //book() 에 대한 기본 생성자가 필요하다.
    //이미 생성자를 사용하고 있기 때문에 () 만 입력해서 나왔던 기본 생성자를 입력해주지 않는다.
    Book(){

    }

    //코드 완성
    Book(String title, String author, int page) {
        this.title = title;
        this.author = author;
        this.page = page;
    }

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

    void displayinfo() {
        System.out.println("Title: " + title);
        System.out.println("Author: " + author);
    }
}

 

중복을 없게 할려면,

package construct;

public class Book {
    String title;
    String author;
    int page;
    //book() 에 대한 기본 생성자가 필요하다.
    //이미 생성자를 사용하고 있기 때문에 () 만 입력해서 나왔던 기본 생성자를 입력해주지 않는다.
    Book(){
        this("","",0);
    }

    //코드 완성
    Book(String title, String author, int page) {
       this(title, author);
    }

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

    void displayinfo() {
        System.out.println("Title: " + title);
        System.out.println("Author: " + author);
    }
}