프로그래밍백엔드 개발자

자바에서 상속 시 메서드 해석 순서(method resolution order)가 어떻게 작동하는지 설명하고, 어떤 잠재적인 함정이 발생할 수 있는지 말씀해 주세요.

Hintsage AI 어시스턴트로 면접 통과

답변.

자바에서 메서드의 오버로딩(overloading)과 오버라이딩(overriding)은 특정 규칙에 따라 이루어집니다. 오버로딩 시, 컴파일러는 호출 위치의 인수 유형에 따라 모든 버전 중에서 가장 적합한 메서드를 컴파일 시 선택합니다.

중요한 점:

  • 모든 클래스와 슈퍼클래스에서 오버로딩된 메서드가 있을 경우, 먼저 현재 클래스에서 가능한 최고 일치를 찾고, 그 다음에 슈퍼클래스에서 찾습니다.
  • 메서드 선택은 실행 단계가 아닌 컴파일 단계에서 이루어집니다.
  • 필요할 경우 타입 변환(widening, autoboxing, varargs)이 적용됩니다.

예제:

class Super { void print(Number n) { System.out.println("Super Number"); } } class Sub extends Super { void print(Integer i) { System.out.println("Sub Integer"); } } ... Sub s = new Sub(); s.print(5); // Sub Integer s.print(5.0); // Super Number

여기서 print(Integer)는 Integer 유형의 인수를 위해 호출되고, Double 유형에 대해서는 부모 메서드가 호출됩니다.

함정 질문.

자식 클래스에서 메서드가 오버라이딩(override)되고 오버로딩(overload)된 경우, 다형성(polymorphism)에서는 어떤 메서드가 호출될 것인가?

답변: 다형성에서는 항상 오버라이딩된 메서드의 경우 실제 객체 유형을 기반으로 메서드 버전이 선택됩니다. 오버로딩된 메서드의 경우, 참조 유형을 기반으로 컴파일 단계에서 선택됩니다.

class A { void test(Number n) { System.out.println("A:Number"); } } class B extends A { void test(Integer n) { System.out.println("B:Integer"); } @Override void test(Number n) { System.out.println("B:Number"); } } ... A obj = new B(); obj.test(1); // B:Number가 호출되나, test(Integer)도 존재함

주제에 대한 세부 사항을 알지 못해 발생한 실제 오류 예.


이야기

개발자가 서브클래스에 오버로딩된 메서드를 추가했는데, 모든 상속 클래스에서 호출될 것으로 기대했습니다. 프로덕션에서 부모 클래스 레퍼런스를 통해 호출하면 객체가 아닌 레퍼런스 유형에 따라 메서드가 선택된다는 사실이 밝혀졌습니다. 결국 필요한 로직이 실행되지 않았습니다.


이야기

대규모 프로젝트에서 equals(Object) 메서드를 equals(MyClass obj) 시그니처로 잘못 오버로딩했습니다. 표준 equals를 대체할 것이라고 생각했습니다. HashSet에서 비교 시 기본 equals(Object)가 작동해 로직 불일치와 데이터 손실을 초래했습니다.


이야기

클래스 계층에 varargs와 함께하는 새로운 버전의 메서드를 추가했을 때, 배열에 대해 필요한 버전이 호출될 것 같았습니다. 그러나 배열을 명시적으로 전달했을 때 컴파일러가 잘못된 오버로딩을 선택해 처리에 문제가 발생했고, 버그는 오랫동안 발견되지 않았습니다.