Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
Tags
- entity
- npm
- 0.5px border
- &연산
- 전역변수
- font-size
- 으
- literal
- TypeScript
- 1px border
- Props
- 타입스크립트
- Strict
- TS
- Websocket
- 문서번호
- ES5
- 당근마켓
- 데이터베이스 #try #이중
- ZOOM
- angular
- 클론코딩
- jwt
- github
- 0.25px border
- 0.75px border
- 10px
- 컴포넌튼
- es6
- 서버리스 #
Archives
- Today
- Total
복잡한뇌구조마냥
[JAVA] Effective Java - 다중정의는 신중히 사용하라 (52) 본문
1. 재정의 vs 다중정의
- 재정의(Overriding)
- 상위 클래스의 메서드와 시그니처가 동일할 때 하위 클래스에서 다시 정의하는 것.
- 호출 대상은 런타임 시점 객체의 실제 타입으로 결정 → 동적 바인딩.
- 다중정의(Overloading)
- 메서드 이름은 같지만, 매개변수 시그니처가 다른 여러 메서드를 정의하는 것.
- 호출 대상은 컴파일 타임에 매개변수의 정적 타입으로 결정 → 정적 바인딩.
class Parent {
void hello(Object o) { System.out.println("Object"); }
void hello(String s) { System.out.println("String"); }
}
Object obj = "text";
Parent p = new Parent();
p.hello(obj); // "Object" — 런타임 타입은 String이지만, 정적 타입 Object 기준으로 선택됨
👉 오버로드는 다형성처럼 동작하지 않으며, 호출 결과가 직관과 달라질 수 있다.
2. 다중정의가 위험한 이유
- 매개변수의 정적 타입이 기준이므로, 런타임 타입은 전혀 고려되지 않는다.
- null 인수는 모호성을 유발한다. (m(String), m(Integer) → m(null) 컴파일 에러)
- 오토박싱, 제네릭, varargs가 얽히면 더 복잡해지고 예측하기 힘들다.
- 자바 8부터 람다/메서드 참조가 추가되면서 혼동이 심화.
- 서로 다른 함수형 인터페이스를 받는 오버로드는 람다식으로 호출 시 모호하거나 의도치 않은 버전이 선택될 수 있다.
- List.remove() 사례
List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
list.remove(1); // index 1 제거
list.remove(Integer.valueOf(1)); // 값 1 제거
→ remove(int) vs remove(Object) 오버로드 혼란.
3. “근본적으로 다른 타입” 조건
다중정의가 안전하려면 매개변수 타입이 근본적으로 달라야 한다.
- 기본 타입 vs 참조 타입
- 클래스 타입 vs 배열 타입
- 인터페이스 타입 vs 배열 타입
- 상하위 관계가 없는 두 클래스(unrelated)
⚠️ 하지만, 자바 5부터 오토박싱과 제네릭이 도입되면서 이 경계가 흐려졌다.
- int vs Integer는 사실상 혼동 가능.
- List<Object> vs List<String>도 제네릭 소거 때문에 근본적으로 다르지 않음.
4. 다중정의 사용 가이드
- 매개변수 개수가 다른 경우는 비교적 안전하다.
- 같은 개수라면, 혼동 가능성이 있다면 메서드 이름을 다르게 짓는 것이 바람직하다.
- write(String) → writeText
- write(byte[]) → writeBytes
- 생성자는 이름을 바꿀 수 없으므로 필연적으로 오버로드된다.
- 이 경우 정적 팩터리 메서드(of(), from(), valueOf() 등)를 고려하라.
- 애매하다면, instanceof 검사 + 명시적 형변환으로 하나의 메서드로 통합하는 것도 방법.
- 람다/메서드 참조를 인수로 받는 경우, 같은 위치에서 서로 다른 함수형 인터페이스를 인자로 받는 오버로드는 만들지 말 것.
5. 실무 팁
- 컴파일러 옵션: -Xlint:overloads를 켜면 혼동 가능성이 있는 다중정의를 경고한다.
- 테스트 필수: null, 경계 값, 람다 등 애매한 케이스를 반드시 단위 테스트에 포함.
- API 안정성: 오버로드가 불려도 결과가 항상 같다면 안전하다.
- 그렇지 않다면 다중정의를 억지로 쓰지 말고, 메서드명을 분리하거나 정적 팩터리를 제공하는 게 더 명확하다.
6. 결론
다중정의는 편리하지만, 호출 규칙은 정적이고 매우 복잡하다.
- 혼란을 일으킬 수 있는 오버로드는 피하라.
- 의미가 다르면 이름을 분리하라.
- 생성자 오버로드는 정적 팩터리로 대체할 수 있다.
- 함수형 인터페이스, 오토박싱, 제네릭과 섞이면 특히 조심하라.
언어가 다중정의를 허용한다고 해서 반드시 써야 하는 것은 아니다.
가장 중요한 원칙: 읽는 사람이 혼동하지 않는 API를 제공하라.
LIST
'BE > JAVA' 카테고리의 다른 글
[JAVA] Effective Java - 일반적으로 통용되는 명명 규칙을 따르라 (68) (2) | 2025.09.01 |
---|---|
[JAVA] Effective Java - 지역변수의 범위를 최소화하라 (57) (1) | 2025.08.31 |
[JAVA] Effective Java - 스트림은 주의해서 사용하라 (45) (0) | 2025.08.24 |
[JAVA] AOP (관점 지향 프로그래밍) 기초 정리 (0) | 2025.08.22 |
[JAVA] Thymeleaf 기초 정리 (0) | 2025.08.20 |