본문 바로가기

Reading/Effective Java

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

소스 파일 하나에 톱레벨 클래스를 여러 개 선언해도 컴파일 에러가 발생하진 않는다.

 

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

/** Dessert.java **/
class Utensil {
    static final String NAME = "pot";
}
class Dessert {
    static final String NAME = "pie";
}

/** Utensil.java **/
class Utensil {
    static final String NAME = "pan";
}

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

 

같은 패키지 상에서 중복된 클래스 이름을 사용할 경우 컴파일 에러를 발생시킨다.

다른 패키지에서 중복된 클래스 이름을 사용할 경우 컴파일 에러는 발생하지 않는다. 

현재 환경은 같은 패키지 상에서 중복된 클래스 이름을 사용하는 경우기 때문에 컴파일 에러가 발생한다.

하지만 컴파일을 아래처럼 명령줄 인수로 다르게 하면 가능은 하다.

 

# java Main으로 실행 시 "pancake" 출력
javac Main.java Dessert.java

# java Main으로 실행 시 "potpie" 출력
javac Main.java Utensil.java

 

 

이처럼 컴파일러에게 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라진다.

 

해결책 및 정리


이런 걱정을 할 필요없이 톱레벨 클래스들을 서로 다른 소스 파일로 분리하면 그만이다.

굳이 여러 톱레벨 클래스를 한 파일에 담고 싶다면 정적 멤버 클래스를 만들자.

 

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";
    }
}

 

읽기 좋고 private으로 선언해 접근 범위도 최소로 관리할 수 있다.

 

소스 파일 하나에는 인터페이스, 클래스 구분 없이 톱레벨 하나만 담자.

컴파일러 순서에 따라 프로그램이 동작이 달라지는 일은 결코 일어나지 않으니까.

 

* 책 본문에는 javac Main.java도 성공하고 javac Main.java Dessert.java 로 컴파일하면 중복정의로 알려준다는데 그렇게 되지 않았다. 패키지가 다르다면 패키지에 맞게 사용하는 클래스에서 지정을 구분할테고, 중복 정의된 클래스가 존재하면 컴파일 타임에 순서를 떠나 컴파일 에러가 발생하는데 어떤 의도로 이 내용이 적혔는지는 모르겠다. 그냥 톱레벨 클래스 하나만 쓰자는 것에만 초점을 맞췄다.

 

 

 

* 위 글은 EffectiveJava 3/E 책 내용을 정리한 글로, 저작권 관련 문제가 있다면 댓글로 남겨주시면 즉각 삭제조치 하겠습니다.