초보개발자 긍.응.성
(이펙티브 자바 3) 25. 톱레벨 클래스는 한 파일에 하나만 담으라 본문
톱 레벨 클래스
톱레벨톱 레벨 클래스는 소스파일에서 가장 바깥에 존재하는 클래스를 말한다. 일반적으로 하나의 소스파일에서는 하나의 톱 레벨 클래스를 가진다. 예로 파일 이름이 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).
이처럼 컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라지므로 반드시 바로 잡아야 할 문제이다.
해결 방법
톱클래스들을 서로 다른 소스 파일로 분리하자. 굳이 여러 톱 레벨 클래스를 한 파일에 담고싶다면 정적 멤버 클래스를 사용하자. 다른 클래스에 딸린 부차적인 클래스라면 이 방법이 더 좋을 것이다.
정리
소스 파일 하나에는 반드시 톱레벨 클래스를 하나만 담자. 이 규칙을 따른다면 소스 파일을 어떤 순서로 컴파일 하든 프로그램의 동작이 달라지는 일은 없을 것이다.
'책 정리 > 이펙티브 자바 3' 카테고리의 다른 글
(이펙티브 자바 3) 5장 제네릭 정리 (0) | 2020.11.25 |
---|---|
(이펙티브 자바 3) 28. 배열보다는 리스트를 사용하라 (0) | 2020.11.23 |
(이펙티브 자바 3) 27. 비검사 경고를 제거하라 (0) | 2020.11.10 |
(이펙티브 자바 3) 26. 로 타입은 사용하지 말라 (0) | 2020.11.07 |
(이펙티브 자바 3) 24. - 멤버 클래스는 되도록 static으로 만들라 (0) | 2020.10.28 |
(이펙티브 자바 3) 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 (0) | 2020.10.27 |
(이펙티브 자바 3) 22. 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2020.10.22 |
(이펙티브 자바 3) 21. 인터페이스는 구현하는 쪽을 생각해 설계하라 (0) | 2020.10.20 |