반응형

ITEM 25 "탑 레벨 클래스는 한 파일에 하나만 담으라"

 

소스 파일 하나에 탑 레벨 클래스를 여러 개 선언해도 자바 컴파일러는 에러를 발생시키진 않는다.

하지만 아무런 득이 없고, 심각한 위험을 감수해야 한다. 한 파일에 여러 클래스를 정의하는데 다른 파일에서도 같은 클래스를 정의할 수 있기 때문에 어느 소스 파일을 먼저 컴파일하느냐에 따라 다른 로직이 수행될 수 있다.

 

public class Utensil {
    static final String NAME = "pan";
}

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

Utensil.java

 

public class Utensil {
    static final String NAME = "pot";
}

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

Dessert.java

 

public class Main {
    public static void main(String[] args) {
        System.out.println(Utensil.NAME + Dessert.NAME);
    }
}

Main.java

 

 

Utensil.java 및 Dessert.java 파일에 같은 클래스가 정의되었을 때 어떤 순서대로 컴파일하느냐에 따라 결과가 달라진다.

 

예를 들어, "javac Main.java Dessert.java" 명령으로 컴파일한다면 컴파일 오류가 난다. 가장 먼저 Main.java 를 컴파일하고, 그 안에서 Utensil 참조를 만나 Utensil.java 파일을 살펴 Utensil 과 Dessert 를 모두 가져온다. 그리고 나서 두 번째 명령줄 인수인 Dessert.java 를 처리하려고 할 때 같은 클래스에 대한 정의가 이미 있어 컴파일 오류가 나는 것이다.

 

"javac Main.java" 나 "javac Main.java Utensil.java" 명령으로 컴파일하면 Dessert.java 참조가 없기 때문에 "pancake" 를 출력한다. 반대로 "javac Dessert.java Main.java" 명령으로 컴파일하면 "potpie" 를 출력한다.

 

컴파일 순서에 따라 결과가 달라지는 문제를 해결하려면, 단순히 탑 레벨 클래스들을 서로 다른 소스 파일로 분리하면 된다. 굳이 여러 탑 레벨 클래스를 한 파일에 담고 싶다면, 정적 멤버 클래스를 고민해보는 것이 좋을 수 있다.

 

Intellij 에서 자바 파일 이름과 다른 클래스가 탑 레벨로 생기면 알아서 아래처럼 경고문구가 발생하면서 컴파일이 되지 않는다. "Class xxxx is public, should be declared in a file named '자바 이름'.java"

그래서 이번 아이템은 솔직히 강제로 지킬 수 있어 걱정 안해도 될 것 같다. ^^

 

반응형

+ Recent posts