소스 파일 하나에 톱레벨 클래스를 여러 개 선언하더라도 자바 컴파일러는 불평하지 않는다.
하지만 아무런 득이 없을 뿐더러 심각한 위험을 감수해야 한다.
한 클래스를 여러 가지로 정의할 수 있고, 그중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하냐에 따라 달라지기 때문이다.
// Utensil.java
class Utensil {
static final String NAME = "pan";
}
class Dessert {
static final String NAME = "cake";
}
Utensil.java 파일에 정의 된 두개의 클래스의 예제이다.
그 다음 Dessert.java 파일에 같은 두 클래스를 담은 클래스를 만들었다.
// Dessert.java
class Utensil {
static final String NAME = "pot";
}
class Dessert {
static final String NAME = "pie";
}
main은 두 클래스의 NAME 을 합쳐서 출력한다.
javac Main.java Dessert.java 로 컴파일하면 컴파일 오류가 클래스를 중복 정의했다고 알려준다.
하지만 javac Main.java Utensil.java 로 컴파일하면 Dessert.java 파일을 작성하기 전과 같이 pancake를 출력한다.
그러나 javac Dessert.java Main.java 명령으로 컴파일 하면 potpie를 출력한다.
이처럼 컴파일러에 어느 소스 파일을 먼저 넣는지에 따라 동작이 달라질 수 있으니 반드시 바로잡아야 한다.
해결책은 간단하다.
톱레벨 클래스들을 서로 다른 소스파일로 분리하거나, 아이템 24의 정적 멤버 클래스를 활용하는 방법이다.
질문 1. 톱레벨 클래스를 한 파일에 정의하면 안되는 이유는?
컴파일러에 어떤 클래스 파일을 먼저 넣느냐에 따라 결과가 달라질 수 있다.
소스 파일을 어떤 순서로 컴파일하든 바이너리 파일이나 프로그램의 동작이 달라지는 일은 없어야 한다.
그러나 사용해야 한다면 정적 멤버 클래스 방식을 활용해볼 수 있겠다.
'JAVA > 이펙티브 자바' 카테고리의 다른 글
27. 비검사 경고를 제거하라 (0) | 2023.07.16 |
---|---|
26. 로 타입을 사용하지 말라 ( 제네릭, 타입 안정성 ) (0) | 2023.07.10 |
24. 멤버 클래스는 되도록 static으로 만들라 ( 멤버 클래스,어댑터 패턴 ) (0) | 2023.07.10 |
23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 ( 클래스 계층구조 ) (0) | 2023.07.06 |
22. 인터페이스는 타입을 정의하는 용도로만 사용하라 ( 상수 공개 ) (0) | 2023.07.06 |