Post

Effective Java - item 25

톱 레벨 클래스는 한 파일에 하나만 담으라

Effective Java - item 25

들어가며

소스 파일 하나에 톱레벨 클래스를 여러 개 선언하더라도 자바 컴파일러는 불평하지 않는다. 하지만 아무런 득이 없을 뿐더러 심각한 위험이 발생할 수도 있다. 컴파일 순서에 따라 결과가 달라질 수도 있기 때문이다.

예시

1
2
3
4
5
6
//  (Page 115)
public class Main {
    public static void main(String[] args) {
        System.out.println(Utensil.NAME + Dessert.NAME);
    }
}

먼저 Main 클래스 하나를 담고있고 Main 클래스는 다른 톱 레벨 클래스 2개 (Utensil, Dessert)를 참조한다.

1
2
3
4
5
6
7
8
//Two classes defined in one file. Don't ever do this! (Page 115)
class Utensil {
   static final String NAME = "pot";
}

class Dessert {
   static final String NAME = "pie";
}

또한 위와 같이 Utensil, Dessert의 클래스가 Utensil.java라는 한 파일에 정의되어있을때는 문제가 없다.

1
2
3
4
5
6
7
8
9
// Two classes defined in one file. Don't ever do this!  (Page 115)
class Utensil {
    static final String NAME = "pan";
}

class Dessert {
    static final String NAME = "cake";
}

하지만 이렇게 똑같은 클래스를 담은 Dessert.java로 만들었다면 문제가 발생할 수도 있다.

문제 발생 이유

  • javac Main.java Dessert.java의 명령으로 컴파일한다면 오류가 나고 Dessert의 중복 정의를 했다고 알려줄 것이다.

  • javac Main.javajavac Main.java Utensil.java명령으로 컴파일한다면 pancake을 출력한다.

  • javac Dessert.java Main.java 명령으로 컴파일 한다면 potpie를 출력한다.

이처럼 컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라지므로 해결해야 한다.

정적 멤버 클래스

해결책은 서로 다른 클래스로 분리하면 그만이지만 굳이 한 파일에 담고싶다면 정적 멤버 클래스를 사용하는 방법을 고민해보면 된다. 다른 클래스에 딸린 부차적인 클래스라면 정적 멤버 클래스로 만드는 쪽이 일반적으로 더 좋다. 읽기 편하고, private으로 선언하면 접근 범위도 최소화 할 수 있기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Static member classes instead of multiple top-level classes (Page 116)
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";
    }
}
This post is licensed under CC BY 4.0 by the author.