on
[교재 EffectiveJava] 아이템 25. 톱레벨 클래스는 한 파일에 하나만...
[교재 EffectiveJava] 아이템 25. 톱레벨 클래스는 한 파일에 하나만...
728x90
톱레벨 클래스
소스 파일 하나에 톱레벨 클래스를 여러개 선언하더라도 자바 컴파일러는 불평하지 않는다. 하지만 아무런 득이 없고 심각한 위험을 감수해야한다.
Utensil.java
package com.java.effective.item25; class Utensil { static final String NAME = "pan"; } class Dessert { static final String NAME = "cake"; }
Main.java
package com.java.effective.item25; public class Main { public static void main(String[] args) { // pancake System.out.println(Utensil.NAME + Dessert.NAME); } }
추가로 우연히 똑같은 두 클래스를 담은 Dessert.java 파일을 생성해보자.
Dessert.java
package com.java.effective.item25; class Utensil { static final String NAME = "pot"; } class Dessert { static final String NAME = "pie"; }
컴파일 에러가 발생한다. 클래스가 중복 정의되었다고 알려준다.
System.out.println(Utensil.NAME + Dessert.NAME);
위 코드의 순서를 보자. (Utensil.java -> Dessert.java)
javac Main.java Utensil.java
컴파일러는 가장 먼저 Main.java를 컴파일하고, 그 안에서 Utensil 참조가 먼저 나오므로, Utemsil.java 파일을 살펴 Utensil, Dessert 모두 찾아낼 것이다. 그런 다음 Dessert.java 를 처리하려고 할때 같은 클래스의 정의가 있음을 알게된다.
javac Main.java javac Main.java Utensil.java
위 명령어로 컴파일하면 Dessert.java 파일을 작성하기 전처럼 정상적으로 결과를 출력한다.
javac Dessert.java Main.java
"potpie" 를 출력한다.
컴파일러에 어느 소스파일을 먼저 건네느냐에 따라 동작이 달라지게된다. 이는 큰 문제점이다.
해결책
아주 간단하다. 톱레켈 클래스(Utensil.java, Dessert.java)를 서로 다른 소스 파일로 분리하면 된다. 굳이 여러 톱레벨 클래스를 한 파일에 담고싶다면, 정적 멤버 클래스를 사용하는 방법을 고민해봐야한다.
다른 클래스에 딸린 부차적인 클래스라면 정적 멤버 클래스로 만드는 쪽이 더 나을것이다. private 로 선언하면 접근 범위도 최소화하여 관리할 수 있다.
정적 멤버 클래스로 바꾼 Test.java
package com.java.effective.item25; 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"; } }
from http://devfunny.tistory.com/562 by ccl(A) rewrite - 2021-10-25 13:27:32