Post

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

소스 파일 하나에 톱레벨 클래스를 여러 개 선언하더라도 자바 컴파일러는 불평하지 않는다.

  • 하지만 아무런 득이 없을 뿐더러 심각한 위험을 감수해야 한다.
    • 한 클래스를 여러 가지로 정의할 수 있다.
    • 그 중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하냐에 따라 달라진다.

두 클래스가 한 파일에 정의되어 있는 예제 😟

Utensil.java

1
2
3
4
5
6
7
class Utensil {
    static final String NAME = "pan";
}

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

Dessert.java

1
2
3
4
5
6
7
class Utensil {
    static final String NAME = "pot";
}

class Dessert {
    static final String NAME = "pie";
}
1
2
3
4
5
public class Main {
    public static void main(String[] args) {
        System.out.println(Utensil.NAME + Dessert.NAME);
    }
}
  • javac Main.java Dessert.java 명령으로 컴파일
    • UtensilDessert 클래스를 중복 정의했다는 컴파일 오류가 발생한다.
  • javac Main.java, javac Main.java Utensil.java 명령으로 컴파일
    • pancake 출력
  • javac Dessert.java Main.java 명령으로 컴파일
    • potpie 출력

컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라지므로 바로 잡을 필요가 있다.

해결 방안 👍

  • 톱레벨 클래스들을 서로 다른 소스 파일로 분리하자.
  • 굳이 여러 톱레벨 클래스를 한 파일에 담고 싶다면 정적 멤버 클래스를 사용하라.
1
2
3
4
5
6
7
8
9
10
11
12
13
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.