|
| 1 | +# 톱레벨 클래스는 한 파일에 하나만 담으라 |
| 2 | + |
| 3 | +## 요약 |
| 4 | + |
| 5 | + 소스 파일 하나에 톱레벨 클래스를 여러 개 선언하더라도 자바 컴파일러는 불평하지 않는다. |
| 6 | + 하지만 심각한 문제를 일으키니 하면 안된다. |
| 7 | + |
| 8 | + |
| 9 | +## 톱레벨 클래스란? |
| 10 | +Apple의 공식 문서에 따르면 톱-레벨의 정의는 다음과 같다. |
| 11 | + |
| 12 | + Any executable statement not written within a function body, |
| 13 | + within a class, or otherwise encapsulated is considered top-level. |
| 14 | + |
| 15 | +함수, 클래스 또는 다른 무언가로 감싸지지 않은 모든 구문은 톱-레벨로 간주된다. |
| 16 | + |
| 17 | +즉, 톱레벨 클래스란 중첩 클래스가 아닌 것을 말한다. |
| 18 | + |
| 19 | +## 코드 구성 |
| 20 | +``` java |
| 21 | +// Main.java |
| 22 | +public class Main { |
| 23 | + |
| 24 | + public static void main(String[] args) { |
| 25 | + System.out.println(Utensil.NAME + Dessert.NAME); |
| 26 | + } |
| 27 | +} |
| 28 | +``` |
| 29 | +``` java |
| 30 | +// Utensil.java |
| 31 | +class Utensil { |
| 32 | + static final String NAME = "pan"; |
| 33 | +} |
| 34 | + |
| 35 | +class Dessert { |
| 36 | + static final String NAME = "cake"; |
| 37 | +} |
| 38 | +``` |
| 39 | +``` java |
| 40 | +// Dessert.java |
| 41 | +class Utensil { |
| 42 | + static final String NAME = "pot"; |
| 43 | +} |
| 44 | + |
| 45 | +class Dessert { |
| 46 | + static final String NAME = "pie"; |
| 47 | +} |
| 48 | +``` |
| 49 | + |
| 50 | +## 문제 발생 |
| 51 | + |
| 52 | +### 컴파일 에러 |
| 53 | + |
| 54 | +`javac Main.java Dessert.java` |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +컴파일 에러가 나도 각 클래스를 중복해서 정의했다고 알려준다. |
| 59 | + |
| 60 | +그 이유는 컴파일러는 다음과 같은 순서로 작동했기 때문이다. |
| 61 | + |
| 62 | +1. 먼저 `Main.java` 컴파일 |
| 63 | +2. 그 안에서 `System.out.println(Utensil.NAME + Dessert.NAME);` 구문을 만나기 때문에 `Utensil.java`를 컴파일 |
| 64 | +3. 2번째 인수로 넘어온 `Dessert.java`을 컴파일 하려고 할 때 같은 클래스가 이미 정의되어 있는 것을 알게된다. |
| 65 | + |
| 66 | +<br> |
| 67 | + |
| 68 | +### Pancake 출력 |
| 69 | + |
| 70 | +`javac Main.java or javac Main.java Utensil.java` |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | +<br> |
| 75 | + |
| 76 | +### Potpie 출력 |
| 77 | +`javac Dessert.java Main.java` |
| 78 | + |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | +## 해결책 |
| 83 | + |
| 84 | +### 톱레벨 클래스들을 서로 다른 소스 파일로 분리 |
| 85 | + |
| 86 | +``` java |
| 87 | +// Utensil.java |
| 88 | +public class Utensil { |
| 89 | + static final String NAME = "pan"; |
| 90 | +} |
| 91 | +``` |
| 92 | +``` java |
| 93 | +// Dessert.java |
| 94 | +public class Dessert { |
| 95 | + static final String NAME = "cake"; |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | + |
| 100 | +### 톱레벨 클래스를 굳이 한 파일에 담고 싶을 때 |
| 101 | +[맴버 클래스는 되도록 static으로 만들어라(아이템 24) By 연로그](https://github.com/woowacourse-study/2022-effective-java/blob/main/04%EC%9E%A5/%EC%95%84%EC%9D%B4%ED%85%9C_24/%EB%A9%A4%EB%B2%84%20%ED%81%B4%EB%9E%98%EC%8A%A4%EB%8A%94%20%EB%90%98%EB%8F%84%EB%A1%9D%20static%EC%9C%BC%EB%A1%9C%20%EB%A7%8C%EB%93%A4%EC%96%B4%EB%9D%BC.md) |
| 102 | + |
| 103 | +``` java |
| 104 | +public class Main { |
| 105 | + |
| 106 | + public static void main(String[] args) { |
| 107 | + System.out.println(Utensil.NAME + Dessert.NAME); |
| 108 | + } |
| 109 | + |
| 110 | + private static class Utensil{ |
| 111 | + static final String NAME = "pan"; |
| 112 | + } |
| 113 | + |
| 114 | + private static class Dessert{ |
| 115 | + static final String NAME = "caks"; |
| 116 | + } |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | + |
| 121 | +## 결론 |
| 122 | +- 한 소스 파일안에 톱레벨 클래스를 하나만 만들자. |
| 123 | +- 사실 여러 톱레벨 클래스를 만들어도 이점이 없다. |
| 124 | +- 터미널을 통해서 javac 명령어를 이용하지 않으면 인텔리제이는 어떤 순서든 컴파일을 해주지 않는다. |
0 commit comments