소스 파일 하나에 톱레벨 클래스를 여러 개 선언해도 컴파일러는 문제를 표시하지 않는다. 하지만 여러 위험들이 있다. 한 클래스를 여러 가지로 정의할 수 있으며, 그중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하냐에 따라 달라지기 때문이다.
Main.java
public class Main {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME);
}
}
Utensil.java - 따라하지 말 것
class Utensil {
static final String NAME = "pan";
}
class Dessert {
static final String NAME = "cake";
}
이 상태에서 Main
을 실행하면 pancake
를 출력한다.
여기서 Dessert.java
파일을 만들어보자.
Dessert.java
class Utensil {
static final String NAME = "pot";
}
class Dessert {
static final String NAME = "pie";
}
javac Main.java Dessert.java
컴파일 할 경우Utensil
과 Dessert
클래스를 중복 정의했다고 알려준다. Main
에서 Dessert
보다 Utensil
참조를 먼저 만나기 때문에 Utensil
과 Dessert
를 찾아낸다. 그 다음 컴파일러가 두 번째 인수로 넘어온 Dessert.java
를 처리하려 할 때 이미 같은 클래스가 정의된 것을 알아챈다.javac Main.java
또는 Main.java Utensil.java
명령pancake
출력javac.Dessert.java Main.java
명령으로 컴파일potpie
출력컴파일 순서에 따라 동작이 달라지니 문제다.
그냥 톱레벨 클래스들 (Utensil, Dessert)를 다른 소스 파일로 분리하면 끝이다. 굳이 여러 톱레벨 클래스를 한 파일에 담고 싶다면 정적 멤버 클래스(아이템 24)를 사용하자.
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";
}
}