본문 바로가기
Java/Effective Java 3E

[이펙티브자바 3판] ITEM25. 톱레벨 클래스는 한 파일에 하나만 담으라

by 잭피 2020. 10. 5.

이번장의 핵심은...

소스 파일 하나에는 반드시 톱 레벨 클래스 (혹은 톱 레벨 인터페이스)를 하나만 담자

이 규칙만 따른다면 컴파일러가 한 클래스에 정의를 여러 개 만들어내는 일은 사라진다

소스 파일을 어떤 순서로 컴파일하든 바이너리 파일이나 프로그램의 동작이 달라지는 일은 결코 일어나지 않을 것이다


소스 파일에 하나의 톱레벨 클래스를 여러 개 선언하더라도 상관없지만,

아무런 득이 없고 심각한 위험을 감수해야 한다

 

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

예) Utensil 클래스와 Dessert 클래스가 Utensil.java라는 한 파일에 정의되어 있다고 해보자

// Utensil.java 에 2개의 클래스가 정의 (따라 하지 말 것!)
class Utensil {
	static final String NAME = "pan";
}
class Dessert {
	static final String NAME = "cake";
}

아래의 메인을 출력해보자

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

pancake라고 출력한다

 

그런데 만약 우연히 똑같은 두 클래스를 담은 Dessert.java라는 파일을 만들었다고 해보자

// 우연히 똑같은 두 클래스를 담은 Dessert.java 에 2개의 클래스가 정의 (따라 하지 말 것!)
class Utensil {
	static final String NAME = "pot";
}
class Dessert {
	static final String NAME = "pie";
}

운 좋게 javac Main.java Dessert.java 명령으로 컴파일하면 컴파일 오류가 나고 Utensil과 Dessert 클래스를 중복 정의했다고 알려줄 것이다 (Main 컴파일 후, 그 안에서 Utensil 참조를 만나면 Utensil.java를 살펴 Utensil과 Dessert를 모두 찾아 낸 후, 다음 Dessert.java를 처리하려 할 때 같은 클래스가 정의되어 있는 것을 알고 컴파일 오류가 발생한다)

 

한편, javac Main,java Utensil.java 명령으로 컴파일하면 pancake를 출력하고,

javac Dessert.java Main.java 명령으로 컴파일하면 potpie를 출력한다

이처럼 컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라지므로 반드시 해결해야 한다

 

해결법은 아주 간단하다

1. 단순히 톱레벨 클래스들을 서로 다른 소스 파일로 분리 (Utensil, Dessert)

2. 굳이 한 파일에 담고 싶다면 정적 멤버 클래스를 사용하는 방법을 고민해봐라

3. 읽기 좋고, private로 선언하면 접근 범위도 최소로 관리할 수 있다

public class Test {
	public static void main(String[] arg) {
		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";
	}
}

 

 

이 글은 “이펙티브 자바 3판” 책 내용을 정리한 글입니다.

만약 저작권 관련 문제가 있다면 “shk3029@kakao.com”로 메일을 보내주시면, 바로 삭제하도록 하겠습니다.

 

댓글