1. 톱 레벨 클래스는 파일 당 하나
최상단에 위치한 클래스는 한 파일에 하나만 있어야 한다. 비록 여러개를 선언하더라도 컴파일은 되지만, 심각한 위험을 감수해야 한다. 동일하게 선언된 클래스 여러 파일 중 어느 것을 먼저 컴파일을 하냐에 따라 결과가 달라지기 때문이다. 아래 예시를 살펴보자.

public class Main {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME);
}
}
위는 메인 클래스를 하나 담고 있고, Utensil 클래스와 Dessert 클래스를 각각 참조하고 있다. 이 때, 두 클래스가 한 파일에 정의되어 있다고 가정해보자.
// 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 이 실행되면서 Utensil 참조를 만나면, Utensil.java 파일을 뒤져 Utensil 과 Dessert 클래스를 모두 찾아낼 것이다. 그 다음, Dessert 참조를 만나게 되었을 때 컴파일 오류를 뱉는 것이다.
만약, 운 나쁘게 javac Main.java Utensil.java 명령으로 컴파일 되었다면?
컴파일 단계에서 오류를 뱉지 못하고 potpie 를 출력한다. 이처럼, 컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라진다.
2. 해결책
톱레벨 클래스들을 서로 다른 소스 파일로 분리하자. 특히, 정적 멤버 클래스를 사용할 수 있다. 다른 클래스에 딸린 부차적 클래스라면, 정적 멤버 클래스로 만드는 편이 읽기 좋고, 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";
}
}'1️⃣ 백앤드 > 이펙티브 자바' 카테고리의 다른 글
| [아이템27] 비검사 경고를 제거하라 (0) | 2024.10.22 |
|---|---|
| [아이템26] 로 타입은 사용하지 말라 (0) | 2024.10.18 |
| [아이템24] 멤버 클래스를 되도록 static 으로 만들어라 (2) | 2024.10.17 |
| [아이템23] 태그 달린 클래스보다는 클래스 계층구조를 활용하라 (0) | 2024.10.16 |
| [아이템22] 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2024.10.15 |