Link
Today
Total
10-17 00:15
Archives
관리 메뉴

초보개발자 긍.응.성

(이펙티브 자바 3) 25. 톱레벨 클래스는 한 파일에 하나만 담으라 본문

책 정리/이펙티브 자바 3

(이펙티브 자바 3) 25. 톱레벨 클래스는 한 파일에 하나만 담으라

긍.응.성 2020. 11. 1. 20:13
반응형

톱 레벨 클래스

톱레벨톱 레벨 클래스는 소스파일에서 가장 바깥에 존재하는 클래스를 말한다. 일반적으로 하나의 소스파일에서는 하나의 톱 레벨 클래스를 가진다. 예로 파일 이름이 SimpleService.java라면 클래스 이름도 SimpleService로 하나의 톱 레벨 클래스를 갖는다.

사실 소스 파일 하나에 톱레벨 클래스를 여러 개 선언하더라도 자바 컴파일러의 동작에는 아무런 문제가 없다. 단 이런 사용은 아무런 득이 없을뿐더러 심각한 위험을 감수해야 하는 행위다.

다수의 톱레벨 클래스 정의의 문제점

한 클래스를 여러 가지로 정의할 수 있으며, 그중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하냐에 따라 달라진다.

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

아래의 Utensil.java과 Dessert.java 소스는 같은 이름의 톱 레벨 클래스를 갖고 있다.

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

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

 

  • Dessert.java
class Utensil {
    static final String NAME = "pot";
}

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

컴파일 순서에 따라 아래와 같은 문자가 출력된다.

no. compile console out
1 javac Main.java (Utensil.java) pancake
2 javac Main.java Dessert.java Compile Error
3 javac Utensil.java Main.java pancake
4 javac Dessert.java Main.java potpie

1. javac Main.java (Utensil.java)

컴파일러는 우선적으로 Main.java를 살핀다. 이후 Main에서 Utensil 참조를 만나면 Utensil.java 파일을 살펴 Utensil과 Dessert를 모두 찾아낸다. 그다음 컴파일러가 두 번째 인자로 Utensile.java가 전달된다면 이는 앞서 Main.java를 처리하며 이미 참조하였기에 Utensil.java에 선언된 Utensil과 Dessert 클래스를 통해 값을 출력하게 된다(pancake).

2. javac Main.java Utensil.java

컴파일러는 1번 경우와 같이 Main.java를 살핀다. 다른 점이라면 두 번째 인자로 Dessert.java가 넘어온다는것이다. 컴파일러는 Dessert.java를 처리할 때 이미 같은 이름의 클래스가 정의되었음을 알게되고 컴파일 오류를 발생시킨다.

3. javac Utensil.java Main.java

먼저 Utensil.java를 처리, 다음에 Main.java를 처리하는 방식으로 순서만 바뀌었지만 1번 경우와 참조하는 소스는 모두 동일하다(pancake).

4. javac Dessert.java Main.java

컴파일러는 우선적으로 Dessert.java를 살피는데 이때 Utensil과 Dessert 클래스를 모두 찾아낸다. 두번째 인자로 받은 이후 Main.java를 처리할 때 Dessert.java에서 찾은 Utensil과 Dessert를 통해 값을 출력한다(potpie).

이처럼 컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라지므로 반드시 바로 잡아야 할 문제이다.

해결 방법

톱클래스들을 서로 다른 소스 파일로 분리하자. 굳이 여러 톱 레벨 클래스를 한 파일에 담고싶다면 정적 멤버 클래스를 사용하자. 다른 클래스에 딸린 부차적인 클래스라면 이 방법이 더 좋을 것이다.

정리

소스 파일 하나에는 반드시 톱레벨 클래스를 하나만 담자. 이 규칙을 따른다면 소스 파일을 어떤 순서로 컴파일 하든 프로그램의 동작이 달라지는 일은 없을 것이다.

반응형
Comments