52. 다중정의는 신중히 사용하라
📝 아이템 52: 다중정의는 신중히 사용하라
🔹 핵심 요약
✅ 다중정의(오버로딩)는 컴파일 타임에 어떤 메서드를 호출할지 결정됨 ✅ 재정의(오버라이딩)는 런타임에 인스턴스 타입에 따라 결정됨 ✅ 다중정의는 혼란을 일으키기 쉬우므로 신중하게 사용해야 함 ✅ 매개변수 개수가 같은 다중정의는 피하는 것이 좋음
📚 필수 개념 정리
💡 다중정의(Overloading)
같은 이름의 메서드를 여러 개 정의하는 것
매개변수 타입이나 개수가 달라야 함
컴파일 타임에 어떤 메서드를 호출할지 결정됨(정적 바인딩)
💡 재정의(Overriding)
상위 클래스의 메서드를 하위 클래스에서 새로 정의하는 것
메서드 시그니처(이름, 매개변수 타입, 반환 타입)가 동일해야 함
실행 시점에 객체의 실제 타입에 따라 메서드가 결정됨(동적 바인딩)
🧩 Java의 바인딩 정리: 오버로딩, 오버라이딩, static, 필드 접근
바인딩(binding)은 코드 속의 이름(변수, 함수 등) 이 실제로 어떤 대상(값, 객체, 메서드 구현 등) 과 연결되는 과정이 연결이 결정되는 시점에 따라 정적 바인딩과 동적 바인딩으로 나뉨
오버로딩
참조 변수의 타입
같은 이름의 메서드가 여러 개 있을 때, 컴파일 시점에 참조 변수 타입을 기준으로 결정됨
오버라이딩
실제 객체의 타입
상속 관계에서 메서드를 재정의하면, 실행 시점에 실제 객체의 타입을 기준으로 결정됨
필드 접근
참조 변수의 타입
필드는 오버라이딩되지 않으며, 컴파일 시점에 참조 변수 타입에 따라 바인딩됨
static 메서드
참조 변수의 타입
static 메서드는 클래스에 귀속되므로 오버라이딩되지 않고, 컴파일 시점에 타입으로 결정됨
🔑 다중정의와 재정의의 차이
재정의된 메서드는 런타임에 실제 객체 타입에 의해 결정됨
다중정의된 메서드는 컴파일 타임의 참조 타입에 의해 결정됨
이로 인해 다중정의는 직관과 다른 동작을 할 수 있음
🚨 다중정의의 위험성
❓ 이 코드의 결과는?
→ 결과는 그 외 그 외 그 외
👉 왜 이런 결과가 나올까?
다중정의된 메서드는 컴파일 타임의 참조 타입에 의해 결정됨
for문에서 c의 컴파일 타임 타입은 항상 Collection<?>
따라서 항상 classify(Collection<?>) 메서드가 호출됨
🔍 List 인터페이스의 remove 메서드와 자동 형변환의 영향
👉 [3] : 오토박싱 및 언박싱은 다중정의 해석을 더 복잡하게 만듦 ⚠️ List 인터페이스에는 remove() 메서드가 다중 정의(overloading)
remove(num1) → int 타입 → 인덱스로 동작 (1번 위치의 요소 제거)
remove(num2) → Integer → Object로 인식되어 값이 1인 요소 제거
🔥 람다와 다중정의 문제
👉 람다 표현식은 여러 함수형 인터페이스에 적용될 수 있어 오버로딩된 메서드에서는 애매함 발생 ⚠️ 이 경우 컴파일 에러가 발생하므로, 명시적 캐스팅이 필요함
🛠️ 메서드 참조와 다중정의 문제
👉 메서드 참조 역시 다중정의 시 예측하기 어려운 동작 가능성
🧪 해결책
🔧 메서드 하나로 통합
모두 Collection 타입으로 배열에 담겼기 때문에 classify(c)는 항상 Collection 버전만 호출되던 문제
instanceof를 사용해서 런타임 시점에 실제 객체 타입을 검사, 동적 바인딩처럼 동작하게 유도
🔒 안전한 다중정의 방법
매개변수 수가 확연히 다르게 하기
매개변수 타입이 근본적으로 다르게 하기
두 타입의 값이 서로 형변환 불가능해야 함
예: String과 StringBuilder
메서드 이름을 다르게 하기
예: ObjectOutputStream의 writeBoolean, writeInt, writeLong 등
🧪 다중정의 대신 메서드 이름 구분하기
🎯 결론
📍 매개변수 수가 같은 다중정의는 가능한 피하자
📍 다중정의하는 대신 메서드 이름을 다르게 하는 것이 안전함
📍 생성자는 이름을 다르게 할 수 없으므로 정적 팩터리 메서드 활용
📍 다중정의 시 각 메서드가 완전히 독립적으로 동작하도록 구현
💭 느낀 점
💡 이번 아이템을 통해 단순히 문법적으로 다중정의랑 재정의를 구분하는 걸 넘어서, 실제 코드가 어떤 방식으로 바인딩되고 실행되는지를 조금 더 명확히 이해
💡 다중정의(overloading)는 자바가 정적 바인딩을 택하는 특성 때문에, 개발자의 직관과 다른 동작을 할 가능성이 있다는 점에서 매우 위험할 수 있음을 체감
💡 단순히 "오류 없이 잘 작동하는 코드"를 쓰는 게 중요한 게 아니라, 읽는 사람이 직관적으로 이해할 수 있는지, 그리고 실제 동작이 그 기대를 배신하지 않는지가 더 중요하다는 사실을 다시 확인
Last updated