하나의 소스 파일에 여러 개의 톱레벨 클래스를 선언해도 컴파일 에러는 발생하지 않지만, 이러한 구현은 혜택이 없을 뿐만 아니라 심각한 위험을 초래할 수 있습니다.
- 한 소스 파일에 톱 레벨 클래스를 여러 개 선언할 경우 컴파일 순서에 따라 결과가 달라질 수 있음
구체적인 예를 보면 아래와 같습니다.
다음과 같이 톱 레벨 클래스인 Utensil과 Dessert를 참조하는 Main 클래스가 있습니다.
Utensil.java 파일에 다음과 같이 Utensil과 Dessert 클래스가 정의되어 있을 경우 Main 클래스를 실행할 경우 pancake를 출력합니다.
이 상태에서 우연히 똑같은 두 클래스를 다음 Dessert.java 파일을 생성했을 경우 명령어에 따라 다른 상황이 발생할 수 있습니다.
1. javac Main.java Dessert.java 명령으로 컴파일
javac Main.java Dessert.java 명령으로 컴파일할 경우 컴파일 오류가 발생하고 Utensil과 Dessert 클래스가 중복 정의했다고 알려줍니다.
컴파일러는 가장 먼저 Main.java를 컴파일하고 그 안에서 Dessert 참조보다 먼저 나오는 Utensil 참조를 만나면 Utensil.java 파일을 살펴 Utensil과 Dessert를 모두 찾아낼 것입니다.
2. javac Main.java 혹은 javac Main.java Utensil.java 명령으로 컴파일
위 명령어로 컴파일 할 경우 앞선 예제처럼 pancake를 출력합니다.
3. javac Dessert.java Main.java 명령으로 컴파일
위 명령어로 컴파일 할 경우 pancake이 아닌 potpie를 출력합니다.
이처럼 컴파일러에 어떤 소스 파일을 먼저 전달하느냐에 따라 동작이 달라지기 때문에 한 파일에 다수의 톱 레벨 클래스를 정의하는 것은 피해야 합니다.
해결책
앞서 언급한 문제에 대한 해결책은 탑 레벨 클래스를 서로 다른 소스 파일로 분리하는 것입니다.
굳이 여러 톱 레벨 클래스를 하나의 파일에 담고 싶다면, 아이템 24에서 언급한 대로 정적 멤버 클래스를 사용하는 것을 권장합니다.
정적 멤버 클래스로 선언할 경우 가독성이 좋아지고 private으로 선언할 경우 접근 범위도 최소로 관리할 수 있기 때문입니다.
정리
톱 레벨 클래스는 한 파일에 하나만 담는 것이 권장됩니다.
이 규칙을 따를 경우, 소스 파일을 어떤 순서로 컴파일하더라도 바이너리 파일이나 프로그램의 동작이 달라지지 않을 것입니다.
참고
이펙티브 자바
이펙티브 자바 완벽 공략 2부 - 백기선 강사님
'JAVA > Effective Java' 카테고리의 다른 글
[아이템 27] 비검사 경고를 제거하라 (1) | 2024.02.16 |
---|---|
[아이템 26] 로 타입은 사용하지 말라 (0) | 2024.02.16 |
[아이템 24] 멤버 클래스는 되도록 static으로 만들라 (0) | 2024.02.08 |
[아이템 23] 태그 달린 클래스보다는 클래스 계층 구조를 활용하라 (0) | 2024.02.07 |
[아이템 22] 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2024.02.07 |