결론
한 개의 소스 파일에는 한 개의 톱 레벨 클래스를 담자.
이 규칙을 따르면 한 클래스에 대해 여러 개의 정의를 만들어내는 일이 사라져 안전합니다.
만약, 굳이 여러 개의 톱 레벨 클래스를 한 개의 소스파일에 담고 싶다면 정적 멤버 클래스를 고민해봅시다.
설명
소스 파일 하나에 톱 레벨 클래스를 여러 개 선언해도, 컴파일러는 아무런 경고조차 내지 않습니다.
하지만 이럴 경우 아무런 장점도 없고, 오히려 컴파일 에러를 내고 출력 결과가 달라지는 등 위험을 일으킬 수 있습니다.
왜냐하면 한 클래스를 여러 가지로 정의하게 되게 되고, 그중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하냐에 따라 달라지기 때문입니다.
[예제] 한 소스 파일에 2개의 톱 레벨 클래스
Utensil.java : "pancake"
Class Utensil {
static final String NAME = "pan";
}
class Desert {
static final String NAME = "cake";
}
Dessert.java : "potpie"
Class Utensil {
static final String NAME = "pot";
}
class Desert {
static final String NAME = "pie";
}
실행 - Main.java
public class Main {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME); //pancake? potpie?
}
}
컴파일 실행
① javac Main.java Dessert.java → 컴파일 오류 : Utensil과 Dessert 클래스 중복 정의
- 컴파일러는 가장 먼저, Main.java를 컴파일합니다. 그 안에서 Utensil 참조를 만나면 Utensil.java 파일을 살펴 Utensil과 Dessert 를 모두 찾아냅니다.
- 그 후, Dessert.java 를 처리하려 할 때 같은 클래스의 정의가 이미 있음을 알게 됩니다.
② javac Main.java / javac Main.java Utensil.java → 정상 실행
③ javac Dessert.java Main.java → 의도되지 않은 "potpie" 출력
- 이처럼 컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라집니다.
해결책 : 톱레벨 클래스 분리
해결책은 아주 간단합니다. 간단히 톱레벨 클래스들(Utensil과 Dessert)을 서로 다른 소스 파일로 분리하면 그만입니다.
굳이 여러 톱레벨 클레스를 한 소스 파일에 담고 싶다면, 정적 멤버 클래스를 고민할 수 있습니다.
다른 클래스에 딸린 부가적인 클래스라면 정적 멤버 클래스로 만드는 쪽이 읽기 좋고, private 으로 선언하면 접근 범위도 최소로 관리할 수 있어 더 낫습니다.
해결책: 정적 멤버 클래스로 변환
public class Test {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME);
}
private static class Utensil {
static final String NAME = "pan";
}
private static class Dessert {
static final String NAME = "cake";
}
}
출처
https://www.yes24.com/Product/Goods/65551284
'책 > effective java' 카테고리의 다른 글
[effective java] item 26. 로 타입은 사용하지 말라 (0) | 2023.08.28 |
---|---|
[effective java] 제 5장. 제네릭 (들어가기 전에, 용어 정리) (0) | 2023.08.28 |
[effective java] item 24. 멤버 클래스는 되도록 static으로 만들라 (0) | 2023.08.21 |
[effective java] item 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 (0) | 2023.08.21 |
[effective java] item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2023.08.21 |