인프런 커뮤니티 질문&답변

Tae Young님의 프로필 이미지
Tae Young

작성한 질문수

(2025) 일주일만에 합격하는 정보처리기사 실기

Java언어 기출문제의 변형

생성자를 언제 접근하는지 존재하는지 안하는지 구분이 헷갈립니다.

해결된 질문

작성

·

66

0

문제풀때 부모, 자식 생성자가 둘다있어도 자식만 실행하는경우, 부모부터 실행하고 자식에게 내려오는경우, static 예외경우를 쉽게 판별하는방법이 있을까요?... 풀다보니 처음에 생성자생성되는부분에서 자꾸 틀립니다

답변 2

1

주말코딩님의 프로필 이미지
주말코딩
지식공유자

안녕하세요,

 

Java 생성자에 원칙이 분명히 있긴 합니다만, 한 줄로 딱 명료하게 설명하기는 어렵습니다.

우선, 기억하면 좋은 케이스와 원칙을 설명드리겠습니다.

 

1. 자식 클래스로 인해서 태어나는 객체의 경우, 부모 클래스의 기본 생성자는 반드시 호출한다. 단, 자식에서 명시적으로 부모의 기본 생성자가 아닌 다른 생성자(ex. 파라미터가 있음)를 부를 때는 예외로 한다.

→ 예를 들어 super(10)을 하면 int 형태 1개짜리 생성자를 부르는 것이지, 기본 생성자를 부르는 것이 아닙니다. 그런데 또 부모 생성자에 갔더니 본인이 스스로 다른 생성자를 부르는 경우에는 그곳을 따라가야 합니다.

 

→ Java 코드에 기본 생성자가 없는 코드가 예제로 나와도 있다고 생각하셔야 합니다. (코드가 변환되는 과정에서 기본 생성자가 알아서 생깁니다.) 다만 아무 일도 일어나지 않습니다.

 

2. 같은 클래스의 생성자는 2번 호출되지 않는다.

→ 이 부분 헷갈려하시는 분들이 특히 많습니다. "생성자가 2번 호출 안되는데 왜 본인들끼리는 여러 번 부르나요?"는 사실 1번 호출되는 것으로 봐야 합니다. 아직 객체가 탄생하지 않은 상태에서 서로 부르고 있는 것이라서요. main 함수 내에서 객체가 탄생할 때 전체적으로 생성자가 호출되는 것이 끝난 경우에는 더 이상 생성자는 호출되지 않습니다. 이건 예제로 살펴봐야 하는 것이라 글로 설명하기는 좀 어렵네요. 아래 예시 코드 보시겠습니다.

class Parent {
    public Parent() {
        this(1);
        System.out.println(2);
    }

    public Parent(int message) {
        System.out.println(message);
    }
}

class Child extends Parent {
    public Child() {
        System.out.println(3);
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
    }
}

위의 코드는 아래와 같이 출력됩니다.

1
2
3

지금 이 상황은 어떻게 해석해야 할까요?

우선, 자식은 부모를 상속 받았으니까 태어날 때 부모 클래스에 있는 생성자를 "무조건" 호출합니다. 보통 기본 생성자를 부르게 되어있죠. 자식 생성자를 보니 super()로 해서 특정 생성자를 부르지 않고 있습니다. 그러면 그냥 부모로 가서 순서대로 보면 되겠습니다.

 

부모 클래스 가보니까 this(1)로 스스로 int 형태 1개짜리 생성자를 부릅니다.

이건 생성자가 2번 실행된 것으로 봐야할까요?

 

아닙니다. 아직 해당 객체가 태어나지 않았습니다. "생성되는 과정"에 있는 것이죠.

이런 류의 코드를 말씀드린 것입니다.

 

3. static의 경우 앞의 형태를 따라간다.

hiding만 생각하시면 됩니다. 부모 형태(변수 앞에 타입 부분)로 태어났는데 static이 붙어 있으면 자식에서 재정의했다고 하더라도 타입 부분에 구현된 것을 사용합니다.

class Parent {
    public static void display() {
        System.out.println("P");
    }
}

class Child extends Parent {
    public static void display() {
        System.out.println("C");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent childAsParent = new Child();
        Child child = new Child();

        parent.display();         
        childAsParent.display();  
        child.display();          
    }
}

위 코드의 출력값:

P
P
C

 

보통 자식이 재정의하면 자식 메서드가 사용됩니다. 그런데 저 경우에는 위의 두 코드가 모두 P로 실행됩니다. 맨 마지막 코드는 왜 C가 될까요? 타입이 Child로 태어났기 때문입니다.

 

 

이 정도로 정리 드릴 수 있을 것 같은데, 다른 것들은 모두 코드를 보면서 이해하는 것이 좋습니다.

글 몇 개로 모든 경우를 설명드리기가 어렵네요.

 

이해에 도움이 되셨을까요?

0

안녕하세요, 인프런 AI 인턴입니다. Tae Young님.

자바에서 생성자 호출 순서는 객체 생성 과정에서 중요한 개념으로, 이를 잘 이해하는 것이 필요합니다. 몇 가지 중요한 원칙과 예외 사항을 정리해 드리겠습니다.

  1. 일반적인 객체 생성 순서:

    • 부모 생성자 호출: 자식 객체를 생성할 때는 먼저 부모 클래스의 생성자가 호출됩니다. 이는 자바 언어의 규칙으로, 자식 클래스의 생성자가 호출되기 전에 부모 클래스의 생성자가 먼저 실행되어야 합니다.
    • 자식 생성자 호출: 부모 생성자 호출이 끝난 후 자식 클래스의 생성자가 호출됩니다.
  2. 명시적 호출:

    • 자식 클래스의 생성자 내부에서 super() 키워드를 사용해 부모 클래스의 특정 생성자를 명시적으로 호출할 수 있습니다.
    • 이를 통해 부모 클래스의 기본 생성자가 아닌 다른 생성자를 호출할 수 있습니다.
  3. static 초기화 블록:

    • static 초기화 블록은 클래스 로드 시 최초 한 번만 실행됩니다. 이는 객체 생성과는 별개로, 클래스가 메모리에 로드될 때 실행됩니다.

질문 주신 부분에 대한 참고자료를 아래에 첨부합니다. 유사한 주제에 대해 다룬 기존의 질문과 답변 링크도 함께 제공하오니, 상세한 설명과 예제를 확인하시기 바랍니다:

각각의 링크에서 생성자 호출 순서 및 흐름에 대한 구체적인 예제를 확인할 수 있습니다. 또한, 질문 내용과 답변들을 통해 실수를 줄이는 데 도움이 될 것입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Tae Young님의 프로필 이미지
Tae Young

작성한 질문수

질문하기