[이펙티브 자바] 아이템 25. 톱레벨 클래스는 한 파일에 하나만 담으라

June·2022년 4월 3일
0

[이펙티브자바]

목록 보기
24/72

소스 파일 하나에 톱레벨 클래스를 여러 개 선언해도 컴파일러는 문제를 표시하지 않는다. 하지만 여러 위험들이 있다. 한 클래스를 여러 가지로 정의할 수 있으며, 그중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하냐에 따라 달라지기 때문이다.

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 컴파일 할 경우
    • 컴파일 오류가 난다. UtensilDessert클래스를 중복 정의했다고 알려준다. Main에서 Dessert보다 Utensil 참조를 먼저 만나기 때문에 UtensilDessert를 찾아낸다. 그 다음 컴파일러가 두 번째 인수로 넘어온 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";
    }
}

0개의 댓글