공부/Java

자바 생성자

Stair 2024. 8. 30. 17:15
반응형
public class MemberInit {
    String name;
    int age;
    int grade;

}
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 = "user1";
    member2.age = 16;
    member2.grade = 80;

    MemberInit[] members = {member1, member2};

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

 

위의 예제를 보자. 회원 객체를 생성하고 나면 name, age, grade 같은 변수에 초기값을 설정한다. 아마도 회원 객체를 제대로 사용하기 위해서는 객체를 생성하자마자 이런 초기값을 설정해야 할 것이다. 이 코드에는 회원의 초기값을 설정하는 부분이 계속 반복된다. 

위 예제를 이전에 배웠던 메서드를 통해 리팩토링 할 수 있다.

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 member : members) {
        System.out.println("이름: " + member.name + " 나이: " + member.age
        + " 성적: " +member2.grade);
    }

}

static void initMember(MemberInit memberInit, String name, int age, int grade){
    memberInit.name = name;
    memberInit.age = age;
    memberInit.grade = grade;
}

 

위 코드는 initMember 메서드를 사용하여 반복을 제거하였다 그런데 이 메서드는 대부분 Member 객체의 멤버 변수를 사용한다. 이런 경우 앞서 객체 지향에서 학습했듯이 속성과 기능을 한 곳에 두는 것이 더 나은 방법이다. 쉽게 이야기해서 Member가 자기 자신의 데이터를 변경하는 기능을 제공하는 것이 좋다.

 

이를 가능하게 해주는 것이 this이다

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

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

 

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 member : members) {
        System.out.println("이름: " + member.name + " 나이: " + member.age
        + " 성적: " +member2.grade);
    }

}

 

initMember()의 코드를 보면 메서드의 매개변수에 정의한 String name과 Member의 멤버 변수의 이름이 String name으로 둘 다 똑같다. 나머지 변수 이름도 name, age, grade로 모두 같다.

 

멤버 변수와 메서드의 매개변수의 이름이 동일하면 어떻게 구분할까?

이 경우 메서드의 매개변수가 더 우선순위를 가진다. 그렇기에 멤버변수를 직접적으로 가리키는 this라는 것을 사용하여 구분한다.

+this가 붙어있다면 무조건 멤버 변수를 사용한다.

 

 

생성자 - 프로그래밍을 하다 보면 객체를 생성하고 이후에 바로 초기값을 할당해야 하는 경우가 많다. 따라서 앞서 initMember()와 같은 메서드를 매번 만들어야 한다. 그래서 대부분의 객체 지향 언어는 객체를 생성하자마자 즉시 필요한 기능을 좀 더 편리하게 수행할 수 있도록 생성자라는 기능을 제공한다. "생성자를 사용하면 객체를 생성하는 시점에 즉시 필요한 기능을 수행할 수 있다."

initMember()와 유사하지만 다른 특징이 있다.

 

생성자의 이름은 클래스 이름과 같아야한다. 따라서 첫 글자도 대문자로 시작한다.

생성자는 반환 타입이 없다. 비워두어야 한다.

나머지는 메서드와 동일하다.

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;
    }
}
public static void main(String[] args) {
    MemberConstruct member1 = new MemberConstruct("member", 15, 90);


}

 

생성자는 인스턴스를 생성하고 나서 즉시 호출된다. 생성자를 호출하는 방법은 다음 코드와 같이 new 명령어 다음에 생성자 이름과 매개변수에 맞추어 인수를 전달하면 된다.

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

생성자 이름은 클래스 이름과 동일하게 지어야 한다 그렇지 않으면 컴파일 에러가 난다.

 

new MemberConstruct("user1", 15, 90)

이렇게 하면 인스턴스를 생성하고 즉시 해당 생성자를 호출한다. 여기서는 Member 인스턴스를 생성하고 바로 MemberConstruct(String name, int age, int grade) 생성자를 호출한다.

 

참고로 new 키워드를 사용해서 객체를 생성할 때 마지막에 괄호()도 포함해야 하는 이유가 바로 생성자 때문이다. 객체를 생성하면서 동시에 생성자를 호출한다는 의미를 포함한다.

 

생성자를 사용함으로써 객체를 생성하면서 동시에 생성 직후에 필요한 작업을 한번에 처리할 수 있다.

또한 생성자를 사용함으로써 코딩 시 제약을 주어 컴파일 오류를 줄여준다.

 

즉 객체를 생성할 때 직접 정의한 생성자가 있다면 "직접 정의한 생성자를 반드시 호출"해야 한다(생성자를 사용하면 필수값 입력을 보장할 수 있다는 뜻이다. 좋은 프로그램은 무한한 자유도가 주어지는 프로그램이 아니라 적절한 제약이 있는 프로그램이다.)

 

여지껏 MemberInit memberInit = new MemberInit(); 처럼 생성자가 없는데 생성자를 호출하는(매개변수가 없는)  생성자를 기본 생성자라고 한다.

 

클래스에 생성자가 하나도 없으면 자바 컴파일러는 매개변수가 없고, 작동하는 코드가 없는 기본 생성자를 자동으로 만들어준다. 단 "생성자가 하나라도 있으면 자바는 기본 생성자를 만들지 않는다"

 

MemberInit 클래스의 경우 생성자를 만들어 놓은 것이 없기 때문에 자바가 기본 생성자인 MemberInit(){}을 만들어 준 것이다.

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


    MemberInit() { //자바가 만드는 기본 생성자

    }
}

이러한 생성자도 메서드처럼 매개변수만 다르게 하여 생성자 오버로딩이 가능하다

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;
    }
    MemberConstruct(String name, int age){
        this.name = name;
        this.age = age;
        this.grade = 50;
    }
}

 

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

        MemberConstruct[] members = {member1, member2};

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

        }

    }
}

 

위와 같은 경우엔 생성자가 오버로딩 되었기 때문에 member2도 객체가 생성된다. grade가 없는 생성자를 호출하면 성적이 50점이 된다.

 

이때 this()라는 기능을 사용하면 생성자 내부에서 자신의 생성자를 호출할 수 있다. this는 인스턴스 자신의 참조값을 가리키기에 자신의 생성자를 호출한다고 생각하면 된다.

 

위 클래스의

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

부분을

MemberConstruct(String name, int age){
    this(name, age, 50);
}

 

이러한 형태로도 바꿀 수 있다.

 

 

마지막으로 책을 활용한 기초 예제이다.

public class Book {
    String title;
    String author;
    int page;

    public Book(){
        this("","", 0);
    }

    public Book(String title, String author){
        this(title,author, 0);
    }


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

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

    }

}

 

public static void main(String[] args) {
    Book book1 = new Book();
    book1.displayInfo();

    Book book2 = new Book("Hello Java", "Seo");
    book2.displayInfo();

    Book book3 = new Book("JPA 프로그래밍", "Kim", 700);
    book3.displayInfo();
}

 

반응형

'공부 > Java' 카테고리의 다른 글

자바 접근 제어자  (5) 2024.08.31
자바 패키지  (0) 2024.08.31
자바 객체 지향 프로그래밍  (0) 2024.08.30
자바 기본형과 참조형  (0) 2024.08.29
자바 클래스와 데이터  (1) 2024.08.29