CodeGym /행동 /JAVA 25 SELF /생성자 오버로딩

생성자 오버로딩

JAVA 25 SELF
레벨 14 , 레슨 4
사용 가능

1. 생성자 오버로딩의 문법

현실에서는 모든 객체가 같은 방식으로 생성되는 경우는 드뭅니다. Person 클래스를 떠올려 봅시다. 어떤 때는 이름만 알고 사람을 만들어야 합니다. 어떤 때는 이름과 나이를 함께 알고 있습니다. 또 어떤 때는 아무것도 모르니 전부 기본값이면 됩니다. 필요하지 않은 매개변수까지 항상 입력하도록 강요하는 것은 이상하겠죠.

생성자 오버로딩은 사용자가 객체를 만들 때 어떤 매개변수는 지정하고 어떤 것은 기본값으로 둘지 선택할 수 있게 하는 방법입니다. 이렇게 하면 클래스가 더 유연하고 사용하기 편해집니다.

비유:
자동차 설계 부서에서 차를 만든다고 해 보죠. 어떤 사람은 기본 트림(에어컨 없음, 핸들과 바퀴만)만 주문하고, 어떤 사람은 “럭셔리”(시트 열선, Wi‑Fi, 심지어 자율주행까지)를 원합니다. 하지만 자동차는 여전히 하나의 같은 클래스이고, 단지 조립 방식이 다를 뿐입니다!

오버로딩은 하나의 클래스에 여러 생성자가 선언되어 있지만 매개변수 목록(개수, 타입, 순서)이 서로 다른 경우를 말합니다. 이들은 모두 클래스와 같은 이름을 가지며 반환 타입이 없습니다.

예제: 오버로딩된 생성자를 가진 클래스

public class Person {
    String name;
    int age;

    // 매개변수 없는 생성자(기본값)
    public Person() {
        this.name = "알 수 없음";
        this.age = 0;
    }

    // 매개변수 1개인 생성자
    public Person(String name) {
        this.name = name;
        this.age = 0;
    }

    // 매개변수 2개인 생성자
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

이제 객체를 다양한 방식으로 생성할 수 있습니다:

Person p1 = new Person();                // 이름 = "알 수 없음", 나이 = 0
Person p2 = new Person("Vasya");         // 이름 = "Vasya", 나이 = 0
Person p3 = new Person("Petya", 25);     // 이름 = "Petya", 나이 = 25

Java는 어떤 생성자를 사용할지 어떻게 판단할까?

Java는 new 뒤에 전달한 인수의 개수와 타입을 봅니다. new Person("Vasya")라고 쓰면 컴파일러는 String 하나를 받는 생성자를 찾습니다. new Person("Petya", 25)라고 쓰면 Stringint 매개변수를 받는 생성자가 필요합니다.

2. 다른 생성자에서 생성자 호출: this(...)

생성자 오버로딩을 하다 보면 코드 일부가 반복되는 경우가 있습니다. 예를 들어 모든 생성자가 반드시 이름을 설정하고, 나이가 지정되지 않으면 0이 되게 하고 싶다고 합시다. 같은 로직을 각 생성자에 복사하지 않으려면 키워드 this(...)를 사용해 한 생성자에서 다른 생성자를 호출할 수 있습니다.

예제

public class Person {
    String name;
    int age;

    // 매개변수 2개인 생성자
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 매개변수 1개인 생성자가 다른 생성자를 호출
    public Person(String name) {
        this(name, 0); // Person(String name, int age)를 호출
    }

    // 매개변수 없는 생성자가 다른 생성자를 호출
    public Person() {
        this("알 수 없음", 0);
    }
}
public Person(String name) {
    this(name, 0); // Person(String, int)를 호출
}
this(...)로 한 생성자에서 다른 생성자 호출

중요 규칙: this(...)를 통한 다른 생성자 호출은 생성자의 첫 번째 줄이어야 합니다!

왜 필요한가요?

  • 코드 중복을 줄입니다.
  • 초기화 로직을 바꾸기로 해도(예: 기본값 변경) 한 곳만 고치면 됩니다.
  • 코드가 더 깔끔해지고 유지보수가 쉬워집니다.

3. 실전 예: 실제 클래스에서의 오버로딩

Account — 은행 계좌 — 클래스를 예로 들어 봅시다. 어떤 때는 소유자 이름만 알고, 어떤 때는 초기 잔액을 곧바로 지정하고, 또 어떤 때는 통화까지 지정하고 싶을 수 있습니다.

오버로딩된 생성자를 가진 클래스 예제

public class Account {
    String owner;
    double balance;
    String currency;

    // 매개변수 3개인 생성자
    public Account(String owner, double balance, String currency) {
        this.owner = owner;
        this.balance = balance;
        this.currency = currency;
    }

    // 매개변수 2개인 생성자(기본 통화 — "EUR")
    public Account(String owner, double balance) {
        this(owner, balance, "EUR");
    }

    // 매개변수 1개인 생성자(잔액 = 0, 통화 = "EUR")
    public Account(String owner) {
        this(owner, 0.0, "EUR");
    }

    // 매개변수 없는 생성자(소유자 — "알 수 없음", 잔액 = 0, 통화 = "EUR")
    public Account() {
        this("알 수 없음", 0.0, "EUR");
    }

    public void printInfo() {
        System.out.println(owner + ": " + balance + " " + currency);
    }
}

사용 예

public class Main {
    public static void main(String[] args) {
        Account acc1 = new Account("Ivan", 1000, "USD");
        Account acc2 = new Account("Mariya", 500);
        Account acc3 = new Account("Pyotr");
        Account acc4 = new Account();

        acc1.printInfo(); // Ivan: 1000.0 USD
        acc2.printInfo(); // Mariya: 500.0 EUR
        acc3.printInfo(); // Pyotr: 0.0 EUR
        acc4.printInfo(); // 알 수 없음: 0.0 EUR
    }
}

왜 편리할까요?

  • 세부 정보 수준을 달리하여 객체를 만들 수 있습니다.
  • 매번 모든 매개변수를 지정할 필요가 없습니다(특히 자주 같은 값일 때).
  • 클래스를 확장하기 쉽습니다. 새 매개변수가 생기면 생성자를 하나 더 추가하면 됩니다.

4. 생성자 오버로딩에서 흔한 실수

오류 №1: 매개변수 타입과 순서가 헷갈림.
만약 Person(String name, int age)Person(int age, String name) 두 생성자가 있다면, 컴파일러는 구분할 수 있지만 클래스 사용자에게는 매우 혼란스러울 수 있습니다. 이런 상황은 피하는 것이 좋습니다.

오류 №2: 기본 생성자 없음.
매개변수가 있는 생성자만 선언하고 나중에 매개변수 없이 객체를 만들려고 하면 컴파일 오류가 발생합니다. 필요하다면 항상 매개변수 없는 기본 생성자를 추가하세요.

오류 №3: 다른 생성자를 첫 줄에서 호출하지 않음.
this(...) 호출은 항상 생성자의 첫 번째 줄이어야 합니다. 그 앞에 무언가를 쓰면 컴파일 오류가 납니다.

오류 №4: 생성자 호출의 순환.
생성자가 자기 자신을(직접 또는 체인을 통해) 호출하면, 무한 재귀 때문에 컴파일 오류가 발생합니다.

오류 №5: 초기화되지 않은 필드.
생성자(또는 호출 체인)에서 어떤 필드의 초기화를 빠뜨리면 객체가 올바르지 않은 상태가 될 수 있습니다. 객체가 생성된 후 모든 필드가 의미 있는 값을 가지는지 확인하세요.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION