diff --git a/EJ3.jpg b/EJ3.jpg
new file mode 100644
index 00000000..744b76aa
Binary files /dev/null and b/EJ3.jpg differ
diff --git a/README.md b/README.md
index aba26664..870f24c2 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,58 @@
-# Effective Java, Third Edition
-
-## Hot News! Source code finally available on GitHub. Happy Hacking!
+# 『이펙티브 자바 3판』(원서: Effective Java 3rd Edition)
+
+
+
+이 저장소는 『이펙티브 자바 3판』([인사이트](http://blog.insightbook.co.kr/), 2018)의 지원 사이트입니다.
+한국어판의 [정오표는 여기](https://docs.google.com/document/d/1PB9DpFff24MtguO3DYKpW-n6xtSC7NbY5A5_Tm55qMs)에서 확인하실 수 있습니다.
+
+---
+
+## 새소식
+:white_check_mark: **2018.11.12** - 출판사에서 이벤트를 진행하네요. [이펙티브 자바 '이판삼판' 이벤트](http://www.insightbook.co.kr/13113). 11월 21일까지입니다. ;)
+
+:white_check_mark: **2018.11.05** - [정오표](https://docs.google.com/document/d/1PB9DpFff24MtguO3DYKpW-n6xtSC7NbY5A5_Tm55qMs)를 추가했습니다.
+
+:white_check_mark: **2018.10.28** - 한국어판 출간에 맞춰 본 저장소의 예제 코드 한글화를 모두 끝마쳤습니다.
+
+:white_check_mark: **2018.10.19** - 한국어판이 11월 1일에 드디어 출간됩니다. 원서보다 출간이 상당히 늦어진 점 죄송합니다. 그에 대한 보상이라긴 뭣하지만, 70여 개의 [원서 오류](https://docs.google.com/document/d/1mAeEgQu4H4ADxa03k7YaVDjIP5vJBvjVIjg3DIvoc8E/edit)를 바로잡을 수 있었고 최근 릴리스된 자바 11까지의 변경도 반영했습니다. 저자가 소스코드를 2018년 8월에서야 공개해서 제가 직접 준비하던 것은 버렸는데, 다행히 저자가 공개한 코드가 훨씬 깔끔하네요. ^^
+
+**룰루랄라~ 책 사러 가기~** [예스24](http://www.yes24.com/24/Goods/65551284) | [교보문고](http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788966262281&orderClick=LAH&Kc=) | [알라딘](https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=171196410) | [인터파크](http://book.interpark.com/product/BookDisplay.do?_method=detail&sc.shopNo=0000400000&sc.prdNo=294626264&sc.saNo=003002001&bid1=search&bid2=product&bid3=title&bid4=001)
+
+:white_check_mark: **2018.07.18** - [저자 직강 동영상](https://www.infoq.com/presentations/effective-java-third-edition?useSponsorshipSuggestions=true&utm_source=presentations_about_java&utm_medium=link&utm_campaign=java)이 공개됐습니다. 스트림과 람다에 집중하여 3판의 특징을 이야기하네요. 어느 분 말씀에 따르면 발표를 귀엽고 신나게 하신다고... ;)
+
+## 『이펙티브 자바 3판』의 주요 특징
+
+* 자바 7, 8, 9 신기능 반영
+ * 함수형 인터페이스, 람다식, 메서드 참조, 스트림
+ * 인터페이스의 디폴트 메서드와 정적 메서드
+ * 제네릭 타입에서의 다이아몬드 연산자를 포함한 타입 추론
+ * @SafeVarargs 애너테이션
+ * try-with-resources 문
+ * Optional〈T〉 인터페이스, java.time, 컬렉션의 편의 팩터리 메서드 등의 새로운 라이브러리 기능
+* 2판까지는 제공하지 않던 [예제 소스코드](https://github.com/WegraLee/effective-java-3e-source-code/tree/master/src/effectivejava) 제공
+
+## 한국어판에 가미된 특징
+
+* 자바 10과 11에서의 변경 사항 반영(본문 내용과 관련된 사항에 한함!)
+* [번역 용어 해설](https://docs.google.com/document/d/1Nw-_FJKre9x7Uy6DZ0NuAFyYUCjBPCpINxqrP0JFuXk/edit) 제공
+* API 문서화 설명(아이템 56)에 영어용과 한글용 모두 수록
+* 본문부터 색인까지, 읽기 쉽도록 원서보다 신경 쓴 편집
+
+## 추천사
+>"고급 자바 개발자로 거듭나고 싶은 분들이라면 꼭 보길 바라며, 대세가 되고 있는 함수형 프로그래밍을 자주 사용하는 실무 개발자에게도 적극 추천합니다."
+**_나상혁**, LG전자 선임연구원, LG전자 SW Colleage JAVA 사내 강사
+
+>"이 책이 유명한 만큼 번역에 대한 부담도 컸을 텐데 책임감을 가지고 정성을 기울여 작업했다는 게 느껴집니다. 조슈아 블로크의 여전한 통찰력에 이복연 님의 친절한 번역이 더해졌습니다."
+**_정상혁**, 네이버 재직, [『네이버를 만든 기술, 읽으면서 배운다: 자바편』](http://www.yes24.com/24/Goods/16813496) 공저자
+
+>"자바 8이 나오자 자바 개발자들이 하나 같이 『이펙티브 자바 3판』이 언제 나오는지 궁금해했습니다. 대폭 개선되었던 자바 6 때 『이펙티브 자바 2판』이 나왔던 것처럼 3판이 나올 때가 되었기 때문입니다. 『이펙티브 자바』 없는 자바 개발은 상상할 수 없으니까요."
+**_박성철**, 우아한형제들 재직
+
+>"『이펙티브 자바』는 자바 언어의 초창기부터 대가의 목소리를 들을 수 있었던 훌륭한 책입니다. 3판에서는 자바 9의 '플랫폼 모듈화'를 다룬 내용을 포함하여 더욱 새로워졌네요. 깊이 있게 자바를 공부하고 싶은 개발자와 학생에게 추천합니다."
+**_유동환**, [『RxJava 프로그래밍』](http://www.yes24.com/24/goods/45506284) 공저자, [『Java 9 모듈 프로그래밍』](http://www.yes24.com/24/Goods/60232732) 역자
+
+## 기타 유용한 정보
+
+* 이 번역서와 직접적인 관련은 없습니다만, 네이버 랩스의 백기선 님이 이 책의 원서를 기반으로 [동영상 강의](https://www.youtube.com/watch?v=X7RXP6EI-5E&list=PLfI752FpVCS8e5ACdi5dpwLdlVkn0QgJJ)를 시리즈로 진행 중입니다. 책만 읽기 따분한 분, 혹은 활자가 아닌 생생한 강의를 듣고 싶은 분께 강추합니다!
+* 국내 자바 개발자들과 소통하며 도움을 얻고자 하시는 분은 [Javawocky](https://www.facebook.com/groups/javawocky/)를 찾아주세요. 이 책의 번역 용어를 정하는 데도 많이 도와주셨습니다.
+* 진지하게 책 저술 혹은 번역에 관심 있으신 분은 [책쓰는 프로그래머 협회](https://www.facebook.com/groups/techbookwriting/)에 들러봐주세요. (제가 쓴 [번역 가이드](https://www.slideshare.net/wegra/ss-52826286)와 [집필 가이드](https://github.com/hanbitmedia/Writing-IT-Books)도 한번 살펴보세요~ ^^)
diff --git a/src/effectivejava/chapter10/item74/IndexOutOfBoundsException.java b/src/effectivejava/chapter10/item74/IndexOutOfBoundsException.java
index c18690d3..21f6a575 100644
--- a/src/effectivejava/chapter10/item74/IndexOutOfBoundsException.java
+++ b/src/effectivejava/chapter10/item74/IndexOutOfBoundsException.java
@@ -1,25 +1,26 @@
package effectivejava.chapter10.item74;
+// 실패 상황을 온전히 포착하도록 수정해본 IndexOutOfBoundsException (405쪽)
public class IndexOutOfBoundsException extends RuntimeException {
private final int lowerBound;
private final int upperBound;
private final int index;
/**
- * Constructs an IndexOutOfBoundsException.
+ * IndexOutOfBoundsException을 생성한다.
*
- * @param lowerBound the lowest legal index value
- * @param upperBound the highest legal index value plus one
- * @param index the actual index value
+ * @param lowerBound 인덱스의 최솟값
+ * @param upperBound 인덱스의 최댓값 + 1
+ * @param index 인덱스의 실젯값
*/
public IndexOutOfBoundsException(int lowerBound, int upperBound,
int index) {
- // Generate a detail message that captures the failure
+ // 실패를 포착하는 상세 메시지를 생성한다.
super(String.format(
- "Lower bound: %d, Upper bound: %d, Index: %d",
+ "최솟값: %d, 최댓값: %d, 인덱스: %d",
lowerBound, upperBound, index));
- // Save failure information for programmatic access
+ // 프로그램에서 이용할 수 있도록 실패 정보를 저장해둔다.
this.lowerBound = lowerBound;
this.upperBound = upperBound;
this.index = index;
diff --git a/src/effectivejava/chapter11/item78/brokenstopthread/StopThread.java b/src/effectivejava/chapter11/item78/brokenstopthread/StopThread.java
index d5bc6659..68780e4e 100644
--- a/src/effectivejava/chapter11/item78/brokenstopthread/StopThread.java
+++ b/src/effectivejava/chapter11/item78/brokenstopthread/StopThread.java
@@ -1,7 +1,7 @@
package effectivejava.chapter11.item78.brokenstopthread;
import java.util.concurrent.*;
-// Broken! - How long would you expect this program to run? (Page 312)
+// 코드 78-1 잘못된 코드 - 이 프로그램은 얼마나 오래 실행될까? (415쪽)
public class StopThread {
private static boolean stopRequested;
@@ -17,4 +17,4 @@ public static void main(String[] args)
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java b/src/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java
index c20c62b6..61642f53 100644
--- a/src/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java
+++ b/src/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java
@@ -1,7 +1,7 @@
package effectivejava.chapter11.item78.fixedstopthread1;
import java.util.concurrent.*;
-// Properly synchronized cooperative thread termination
+// 코드 78-2 적절히 동기화해 스레드가 정상 종료한다. (416쪽)
public class StopThread {
private static boolean stopRequested;
@@ -25,4 +25,4 @@ public static void main(String[] args)
TimeUnit.SECONDS.sleep(1);
requestStop();
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java b/src/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java
index 3a11ab2a..1e9e7315 100644
--- a/src/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java
+++ b/src/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java
@@ -1,7 +1,7 @@
package effectivejava.chapter11.item78.fixedstopthread2;
import java.util.concurrent.*;
-// Cooperative thread termination with a volatile field
+// 코드 78-3 volatile 필드를 사용해 스레드가 정상 종료한다. (417쪽)
public class StopThread {
private static volatile boolean stopRequested;
diff --git a/src/effectivejava/chapter11/item79/ForwardingSet.java b/src/effectivejava/chapter11/item79/ForwardingSet.java
index 9b0c83ea..0398b587 100644
--- a/src/effectivejava/chapter11/item79/ForwardingSet.java
+++ b/src/effectivejava/chapter11/item79/ForwardingSet.java
@@ -1,7 +1,7 @@
package effectivejava.chapter11.item79;
import java.util.*;
-// Reusable forwarding class (Page XXX)
+// 재사용할 수 있는 전달 클래스 (118쪽의 코드 18-3 재사용)
public class ForwardingSet implements Set {
private final Set s;
public ForwardingSet(Set s) { this.s = s; }
diff --git a/src/effectivejava/chapter11/item79/ObservableSet.java b/src/effectivejava/chapter11/item79/ObservableSet.java
index 82ffb00f..82af1ef9 100644
--- a/src/effectivejava/chapter11/item79/ObservableSet.java
+++ b/src/effectivejava/chapter11/item79/ObservableSet.java
@@ -2,10 +2,11 @@
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
-// Broken - invokes alien method from synchronized block!
+// 관찰자 패턴을 구현하여, 원소가 추가되면 알려주는 집합 (420-425쪽)
public class ObservableSet extends ForwardingSet {
public ObservableSet(Set set) { super(set); }
+// 코드 79-1 잘못된 코드. 동기화 블록 안에서 외계인 메서드를 호출한다. (420쪽)
// private final List> observers
// = new ArrayList<>();
@@ -28,7 +29,7 @@ public class ObservableSet extends ForwardingSet {
// }
// }
-// // Alien method moved outside of synchronized block - open calls
+// // 코드 79-3 외계인 메서드를 동기화 블록 바깥으로 옮겼다. - 열린 호출 (424쪽)
// private void notifyElementAdded(E element) {
// List> snapshot = null;
// synchronized(observers) {
@@ -38,7 +39,7 @@ public class ObservableSet extends ForwardingSet {
// observer.added(this, element);
// }
- // Thread-safe observable set with CopyOnWriteArrayList
+ // 코드 79-4 CopyOnWriteArrayList를 사용해 구현한 스레드 안전하고 관찰 가능한 집합 (425쪽)
private final List> observers =
new CopyOnWriteArrayList<>();
@@ -65,7 +66,7 @@ private void notifyElementAdded(E element) {
@Override public boolean addAll(Collection extends E> c) {
boolean result = false;
for (E element : c)
- result |= add(element); // Calls notifyElementAdded
+ result |= add(element); // notifyElementAdded를 호출한다.
return result;
}
}
diff --git a/src/effectivejava/chapter11/item79/SetObserver.java b/src/effectivejava/chapter11/item79/SetObserver.java
index 9b5bf252..5b9e527c 100644
--- a/src/effectivejava/chapter11/item79/SetObserver.java
+++ b/src/effectivejava/chapter11/item79/SetObserver.java
@@ -1,7 +1,7 @@
package effectivejava.chapter11.item79;
-// Set obeserver callback interface - Page 266
+// 집합 관찰자 콜백 인터페이스 (421쪽)
public interface SetObserver {
- // Invoked when an element is added to the observable set
+ // ObservableSet에 원소가 더해지면 호출된다.
void added(ObservableSet set, E element);
}
diff --git a/src/effectivejava/chapter11/item79/Test1.java b/src/effectivejava/chapter11/item79/Test1.java
index ea1ae9ea..93d10499 100644
--- a/src/effectivejava/chapter11/item79/Test1.java
+++ b/src/effectivejava/chapter11/item79/Test1.java
@@ -1,7 +1,7 @@
package effectivejava.chapter11.item79;
import java.util.*;
-// Simple test of ObservableSet - Page 318
+// ObservableSet 동작 확인 #1 - 0부터 99까지 출력한다. (422쪽)
public class Test1 {
public static void main(String[] args) {
ObservableSet set =
diff --git a/src/effectivejava/chapter11/item79/Test2.java b/src/effectivejava/chapter11/item79/Test2.java
index 275f092c..5896343e 100644
--- a/src/effectivejava/chapter11/item79/Test2.java
+++ b/src/effectivejava/chapter11/item79/Test2.java
@@ -1,7 +1,7 @@
package effectivejava.chapter11.item79;
import java.util.*;
-// More complex test of ObservableSet - Page 318-9
+// ObservableSet 동작 확인 #2 - 정숫값이 23이면 자신의 구독을 해지한다. (422쪽)
public class Test2 {
public static void main(String[] args) {
ObservableSet set =
@@ -10,7 +10,7 @@ public static void main(String[] args) {
set.addObserver(new SetObserver<>() {
public void added(ObservableSet s, Integer e) {
System.out.println(e);
- if (e == 23)
+ if (e == 23) // 값이 23이면 자신을 구독해지한다.
s.removeObserver(this);
}
});
diff --git a/src/effectivejava/chapter11/item79/Test3.java b/src/effectivejava/chapter11/item79/Test3.java
index d7534224..13fd386f 100644
--- a/src/effectivejava/chapter11/item79/Test3.java
+++ b/src/effectivejava/chapter11/item79/Test3.java
@@ -4,13 +4,13 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-// Simple test of ObservableSet - Page 319
+// ObservableSet 동작 확인 #3
public class Test3 {
public static void main(String[] args) {
ObservableSet set =
new ObservableSet<>(new HashSet<>());
-// Observer that uses a background thread needlessly
+// 코드 79-2 쓸데없이 백그라운드 스레드를 사용하는 관찰자 (423쪽)
set.addObserver(new SetObserver<>() {
public void added(ObservableSet s, Integer e) {
System.out.println(e);
@@ -31,4 +31,4 @@ public void added(ObservableSet s, Integer e) {
for (int i = 0; i < 100; i++)
set.add(i);
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter11/item81/ConcurrentTimer.java b/src/effectivejava/chapter11/item81/ConcurrentTimer.java
index c9f2304c..aaee2221 100644
--- a/src/effectivejava/chapter11/item81/ConcurrentTimer.java
+++ b/src/effectivejava/chapter11/item81/ConcurrentTimer.java
@@ -1,9 +1,9 @@
package effectivejava.chapter11.item81;
import java.util.concurrent.*;
-// Simple framework for timing concurrent execution 327
+// 코드 81-3 동시 실행 시간을 재는 간단한 프레임워크 (433-434쪽)
public class ConcurrentTimer {
- private ConcurrentTimer() { } // Noninstantiable
+ private ConcurrentTimer() { } // 인스턴스 생성 불가
public static long time(Executor executor, int concurrency,
Runnable action) throws InterruptedException {
@@ -13,22 +13,22 @@ public static long time(Executor executor, int concurrency,
for (int i = 0; i < concurrency; i++) {
executor.execute(() -> {
- ready.countDown(); // Tell timer we're ready
+ ready.countDown(); // 타이머에게 준비를 마쳤음을 알린다.
try {
- start.await(); // Wait till peers are ready
+ start.await(); // 모든 작업자 스레드가 준비될 때까지 기다린다.
action.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
- done.countDown(); // Tell timer we're done
+ done.countDown(); // 타이머에게 작업을 마쳤음을 알린다.
}
});
}
- ready.await(); // Wait for all workers to be ready
+ ready.await(); // 모든 작업자가 준비될 때까지 기다린다.
long startNanos = System.nanoTime();
- start.countDown(); // And they're off!
- done.await(); // Wait for all workers to finish
+ start.countDown(); // 작업자들을 깨운다.
+ done.await(); // 모든 작업자가 일을 끝마치기를 기다린다.
return System.nanoTime() - startNanos;
}
}
diff --git a/src/effectivejava/chapter11/item81/Intern.java b/src/effectivejava/chapter11/item81/Intern.java
index 0e422c94..9d2aa27b 100644
--- a/src/effectivejava/chapter11/item81/Intern.java
+++ b/src/effectivejava/chapter11/item81/Intern.java
@@ -1,9 +1,9 @@
package effectivejava.chapter11.item81;
import java.util.concurrent.*;
-// Concurrent canonicalizing map atop ConcurrentMap - Pages 273-274
+// ConcurrentMap으로 구현한 동시성 정규화 맵
public class Intern {
- // Concurrent canonicalizing map atop ConcurrentMap - not optimal
+ // 코드 81-1 ConcurrentMap으로 구현한 동시성 정규화 맵 - 최적은 아니다. (432쪽)
private static final ConcurrentMap map =
new ConcurrentHashMap<>();
@@ -12,7 +12,7 @@ public class Intern {
// return previousValue == null ? s : previousValue;
// }
- // Concurrent canonicalizing map atop ConcurrentMap - faster!
+ // 코드 81-2 ConcurrentMap으로 구현한 동시성 정규화 맵 - 더 빠르다! (432쪽)
public static String intern(String s) {
String result = map.get(s);
if (result == null) {
@@ -22,4 +22,4 @@ public static String intern(String s) {
}
return result;
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter11/item83/Initialization.java b/src/effectivejava/chapter11/item83/Initialization.java
index 15f40bff..b876732d 100644
--- a/src/effectivejava/chapter11/item83/Initialization.java
+++ b/src/effectivejava/chapter11/item83/Initialization.java
@@ -1,12 +1,12 @@
package effectivejava.chapter11.item83;
-// Initialization styles - Pages 333-
+// 다양한 초기화 방식 (443-445쪽)
public class Initialization {
- // Normal initialization of an instance field4 - Page 282
+ // 코드 83-1 인스턴스 필드를 초기화하는 일반적인 방법 (443쪽)
private final FieldType field1 = computeFieldValue();
- // Lazy initialization of instance field4 - synchronized accessor - Page 333
+ // 코드 83-2 인스턴스 필드의 지연 초기화 - synchronized 접근자 방식 (443쪽)
private FieldType field2;
private synchronized FieldType getField2() {
if (field2 == null)
@@ -14,7 +14,7 @@ private synchronized FieldType getField2() {
return field2;
}
- // Lazy initialization holder class idiom for static fields - Page 334
+ // 코드 83-3 정적 필드용 지연 초기화 홀더 클래스 관용구 (443쪽)
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
@@ -22,23 +22,23 @@ private static class FieldHolder {
private static FieldType getField() { return FieldHolder.field; }
- // Double-check idiom for lazy initialization of instance fields - Page 334
+ // 코드 83-4 인스턴스 필드 지연 초기화용 이중검사 관용구 (444쪽)
private volatile FieldType field4;
private FieldType getField4() {
FieldType result = field4;
- if (result != null) // First check (no locking)
+ if (result != null) // 첫 번째 검사 (락 사용 안 함)
return result;
synchronized(this) {
- if (field4 == null) // Second check (with locking)
+ if (field4 == null) // 두 번째 검사 (락 사용)
field4 = computeFieldValue();
return field4;
}
}
- // Single-check idiom - can cause repeated initialization! - Page 334
+ // 코드 83-5 단일검사 관용구 - 초기화가 중복해서 일어날 수 있다! (445쪽)
private volatile FieldType field5;
private FieldType getField5() {
diff --git a/src/effectivejava/chapter11/item84/SlowCountDownLatch.java b/src/effectivejava/chapter11/item84/SlowCountDownLatch.java
index d0f1e892..098d765b 100644
--- a/src/effectivejava/chapter11/item84/SlowCountDownLatch.java
+++ b/src/effectivejava/chapter11/item84/SlowCountDownLatch.java
@@ -1,6 +1,6 @@
package effectivejava.chapter11.item84;
-// Awful CountDownLatch implementation - busy-waits incessantly! - Pages 336-7
+// 코드 84-1 끔찍한 CountDownLatch 구현 - 바쁜 대기 버전! (447쪽)
public class SlowCountDownLatch {
private int count;
diff --git a/src/effectivejava/chapter12/item85/DeserializationBomb.java b/src/effectivejava/chapter12/item85/DeserializationBomb.java
index 7a5de631..9f15c488 100644
--- a/src/effectivejava/chapter12/item85/DeserializationBomb.java
+++ b/src/effectivejava/chapter12/item85/DeserializationBomb.java
@@ -4,7 +4,7 @@
import java.util.HashSet;
import java.util.Set;
-// Deserialization bomb - deserializing this stream takes forever - Page 340
+// 코드 85-1 역직렬화 폭탄 - 이 스트림의 역직렬화는 영원히 계속된다. (451-452쪽)
public class DeserializationBomb {
public static void main(String[] args) throws Exception {
System.out.println(bomb().length);
@@ -18,7 +18,7 @@ static byte[] bomb() {
for (int i = 0; i < 100; i++) {
Set t1 = new HashSet<>();
Set t2 = new HashSet<>();
- t1.add("foo"); // make it not equal to t2
+ t1.add("foo"); // t1을 t2와 다르게 만든다.
s1.add(t1);
s1.add(t2);
s2.add(t1);
@@ -26,6 +26,6 @@ static byte[] bomb() {
s1 = t1;
s2 = t2;
}
- return serialize(root);
+ return serialize(root); // 이 메서드는 effectivejava.chapter12.Util 클래스에 정의되어 있다.
}
}
diff --git a/src/effectivejava/chapter12/item87/StringList.java b/src/effectivejava/chapter12/item87/StringList.java
index b50989c2..9a213e9e 100644
--- a/src/effectivejava/chapter12/item87/StringList.java
+++ b/src/effectivejava/chapter12/item87/StringList.java
@@ -1,35 +1,34 @@
package effectivejava.chapter12.item87;
import java.io.*;
-// StringList with a reasonable custom serialized form - Page 349
+// 코드 87-3 합리적인 커스텀 직렬화 형태를 갖춘 StringList (462-463쪽)
public final class StringList implements Serializable {
private transient int size = 0;
private transient Entry head = null;
- // No longer Serializable!
+ // 이제는 직렬화되지 않는다.
private static class Entry {
String data;
Entry next;
Entry previous;
}
- // Appends the specified string to the list
+ // 지정한 문자열을 이 리스트에 추가한다.
public final void add(String s) { }
/**
- * Serialize this {@code StringList} instance.
+ * 이 {@code StringList} 인스턴스를 직렬화한다.
*
- * @serialData The size of the list (the number of strings
- * it contains) is emitted ({@code int}), followed by all of
- * its elements (each a {@code String}), in the proper
- * sequence.
+ * @serialData 이 리스트의 크기(포함된 문자열의 개수)를 기록한 후
+ * ({@code int}), 이어서 모든 원소를(각각은 {@code String})
+ * 순서대로 기록한다.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
s.defaultWriteObject();
s.writeInt(size);
- // Write out all elements in the proper order.
+ // 모든 원소를 올바른 순서로 기록한다.
for (Entry e = head; e != null; e = e.next)
s.writeObject(e.data);
}
@@ -39,10 +38,10 @@ private void readObject(ObjectInputStream s)
s.defaultReadObject();
int numElements = s.readInt();
- // Read in all elements and insert them in list
+ // 모든 원소를 읽어 이 리스트에 삽입한다.
for (int i = 0; i < numElements; i++)
add((String) s.readObject());
}
- // Remainder omitted
+ // 나머지 코드는 생략
}
diff --git a/src/effectivejava/chapter12/item89/enumsingleton/Elvis.java b/src/effectivejava/chapter12/item89/enumsingleton/Elvis.java
index 2f1a24be..c47cea09 100644
--- a/src/effectivejava/chapter12/item89/enumsingleton/Elvis.java
+++ b/src/effectivejava/chapter12/item89/enumsingleton/Elvis.java
@@ -2,7 +2,7 @@
import java.util.*;
-// Enum singleton - the preferred approach - Page 311
+// 코드 89-4 열거 타입 싱글턴(선호 방식) - 전통적인 싱글턴보다 우수하다. (478쪽)
public enum Elvis {
INSTANCE;
private String[] favoriteSongs =
@@ -10,4 +10,4 @@ public enum Elvis {
public void printFavorites() {
System.out.println(Arrays.toString(favoriteSongs));
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter12/item90/Period.java b/src/effectivejava/chapter12/item90/Period.java
index 71aaf712..a7d5a929 100644
--- a/src/effectivejava/chapter12/item90/Period.java
+++ b/src/effectivejava/chapter12/item90/Period.java
@@ -1,27 +1,27 @@
package effectivejava.chapter12.item90;
-// Period class with serialization proxy - Pages 363-364
+// 직렬화 프록시를 사용한 Period 클래스 (479-480쪽)
import java.util.*;
import java.io.*;
-// Immutable class that uses defensive copying
+// 방어적 복사를 사용하는 불변 클래스
public final class Period implements Serializable {
private final Date start;
private final Date end;
/**
- * @param start the beginning of the period
- * @param end the end of the period; must not precede start
- * @throws IllegalArgumentException if start is after end
- * @throws NullPointerException if start or end is null
+ * @param start 시작 시각
+ * @param end 종료 시각; 시작 시각보다 뒤여야 한다.
+ * @throws IllegalArgumentException 시작 시각이 종료 시각보다 늦을 때 발생한다.
+ * @throws NullPointerException start나 end가 null이면 발행한다.
*/
public Period(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0)
throw new IllegalArgumentException(
- start + " after " + end);
+ start + "가 " + end + "보다 늦다.");
}
public Date start () { return new Date(start.getTime()); }
@@ -31,7 +31,7 @@ public Period(Date start, Date end) {
public String toString() { return start + " - " + end; }
- // Serialization proxy for Period class
+ // 코드 90-1 Period 클래스용 직렬화 프록시 (479쪽)
private static class SerializationProxy implements Serializable {
private final Date start;
private final Date end;
@@ -42,17 +42,17 @@ private static class SerializationProxy implements Serializable {
}
private static final long serialVersionUID =
- 234098243823485285L; // Any number will do (Item 87)
+ 234098243823485285L; // 아무 값이나 상관없다. (아이템 87)
}
- // writeReplace method for the serialization proxy pattern
+ // 직렬화 프록시 패턴용 writeReplace 메서드 (480쪽)
private Object writeReplace() {
return new SerializationProxy(this);
}
- // readObject method for the serialization proxy pattern
+ // 직렬화 프록시 패턴용 readObject 메서드 (480쪽)
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
- throw new InvalidObjectException("Proxy required");
+ throw new InvalidObjectException("프록시가 필요합니다.");
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter2/item2/builder/NutritionFacts.java b/src/effectivejava/chapter2/item2/builder/NutritionFacts.java
index 0c630099..1fb22fec 100644
--- a/src/effectivejava/chapter2/item2/builder/NutritionFacts.java
+++ b/src/effectivejava/chapter2/item2/builder/NutritionFacts.java
@@ -1,6 +1,6 @@
package effectivejava.chapter2.item2.builder;
-// Builder Pattern (Page 13)
+// 코드 2-3 빌더 패턴 - 점층적 생성자 패턴과 자바빈즈 패턴의 장점만 취했다. (17~18쪽)
public class NutritionFacts {
private final int servingSize;
private final int servings;
@@ -10,11 +10,11 @@ public class NutritionFacts {
private final int carbohydrate;
public static class Builder {
- // Required parameters
+ // 필수 매개변수
private final int servingSize;
private final int servings;
- // Optional parameters - initialized to default values
+ // 선택 매개변수 - 기본값으로 초기화한다.
private int calories = 0;
private int fat = 0;
private int sodium = 0;
@@ -52,4 +52,4 @@ public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
.calories(100).sodium(35).carbohydrate(27).build();
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java b/src/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java
index b26ab600..a2d3367f 100644
--- a/src/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java
+++ b/src/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java
@@ -1,11 +1,11 @@
package effectivejava.chapter2.item2.hierarchicalbuilder;
-// Subclass with hierarchical builder (Page 15)
+// 코드 2-6 칼초네 피자 - 계층적 빌더를 활용한 하위 클래스 (20~21쪽)
public class Calzone extends Pizza {
private final boolean sauceInside;
public static class Builder extends Pizza.Builder {
- private boolean sauceInside = false; // Default
+ private boolean sauceInside = false; // 기본값
public Builder sauceInside() {
sauceInside = true;
@@ -25,7 +25,7 @@ private Calzone(Builder builder) {
}
@Override public String toString() {
- return String.format("Calzone with %s and sauce on the %s",
- toppings, sauceInside ? "inside" : "outside");
+ return String.format("%s로 토핑한 칼초네 피자 (소스는 %s에)",
+ toppings, sauceInside ? "안" : "바깥");
}
}
diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java b/src/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java
index 3e8c04f8..081e9aeb 100644
--- a/src/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java
+++ b/src/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java
@@ -2,7 +2,7 @@
import java.util.Objects;
-// Subclass with hierarchical builder (Page 15)
+// 코드 2-5 뉴욕 피자 - 계층적 빌더를 활용한 하위 클래스 (20쪽)
public class NyPizza extends Pizza {
public enum Size { SMALL, MEDIUM, LARGE }
private final Size size;
@@ -27,6 +27,6 @@ private NyPizza(Builder builder) {
}
@Override public String toString() {
- return "New York Pizza with " + toppings;
+ return toppings + "로 토핑한 뉴욕 피자";
}
}
diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java b/src/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java
index 77925cda..1a9b145c 100644
--- a/src/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java
+++ b/src/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java
@@ -1,9 +1,10 @@
package effectivejava.chapter2.item2.hierarchicalbuilder;
import java.util.*;
-// Builder pattern for class hierarchies (Page 14)
+// 코드 2-4 계층적으로 설계된 클래스와 잘 어울리는 빌더 패턴 (19쪽)
-// Note that the underlying "simulated self-type" idiom allows for arbitrary fluid hierarchies, not just builders
+// 참고: 여기서 사용한 '시뮬레이트한 셀프 타입(simulated self-type)' 관용구는
+// 빌더뿐 아니라 임의의 유동적인 계층구조를 허용한다.
public abstract class Pizza {
public enum Topping { HAM, MUSHROOM, ONION, PEPPER, SAUSAGE }
@@ -18,11 +19,12 @@ public T addTopping(Topping topping) {
abstract Pizza build();
- // Subclasses must override this method to return "this"
+ // 하위 클래스는 이 메서드를 재정의(overriding)하여
+ // "this"를 반환하도록 해야 한다.
protected abstract T self();
}
Pizza(Builder> builder) {
- toppings = builder.toppings.clone(); // See Item 50
+ toppings = builder.toppings.clone(); // 아이템 50 참조
}
}
diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java b/src/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java
index 191fd094..40aecc8a 100644
--- a/src/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java
+++ b/src/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java
@@ -3,7 +3,7 @@
import static effectivejava.chapter2.item2.hierarchicalbuilder.Pizza.Topping.*;
import static effectivejava.chapter2.item2.hierarchicalbuilder.NyPizza.Size.*;
-// Using the hierarchical builder (Page 16)
+// 계층적 빌더 사용 (21쪽)
public class PizzaTest {
public static void main(String[] args) {
NyPizza pizza = new NyPizza.Builder(SMALL)
diff --git a/src/effectivejava/chapter2/item2/javabeans/NutritionFacts.java b/src/effectivejava/chapter2/item2/javabeans/NutritionFacts.java
index a5e4d81f..f08789a3 100644
--- a/src/effectivejava/chapter2/item2/javabeans/NutritionFacts.java
+++ b/src/effectivejava/chapter2/item2/javabeans/NutritionFacts.java
@@ -1,10 +1,10 @@
package effectivejava.chapter2.item2.javabeans;
-// JavaBeans Pattern - allows inconsistency, mandates mutability (pages 11-12)
+// 코드 2-2 자바빈즈 패턴 - 일관성이 깨지고, 불변으로 만들 수 없다. (16쪽)
public class NutritionFacts {
- // Parameters initialized to default values (if any)
- private int servingSize = -1; // Required; no default value
- private int servings = -1; // Required; no default value
+ // 매개변수들은 (기본값이 있다면) 기본값으로 초기화된다.
+ private int servingSize = -1; // 필수; 기본값 없음
+ private int servings = -1; // 필수; 기본값 없음
private int calories = 0;
private int fat = 0;
private int sodium = 0;
@@ -27,4 +27,4 @@ public static void main(String[] args) {
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java b/src/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java
index 230e33cd..f1581bfd 100644
--- a/src/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java
+++ b/src/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java
@@ -1,13 +1,13 @@
package effectivejava.chapter2.item2.telescopingconstructor;
-// Telescoping constructor pattern - does not scale well! (Pages 10-11)
+// 코드 2-1 점층적 생성자 패턴 - 확장하기 어렵다! (14~15쪽)
public class NutritionFacts {
- private final int servingSize; // (mL) required
- private final int servings; // (per container) required
- private final int calories; // (per serving) optional
- private final int fat; // (g/serving) optional
- private final int sodium; // (mg/serving) optional
- private final int carbohydrate; // (g/serving) optional
+ private final int servingSize; // (mL, 1회 제공량) 필수
+ private final int servings; // (회, 총 n회 제공량) 필수
+ private final int calories; // (1회 제공량당) 선택
+ private final int fat; // (g/1회 제공량) 선택
+ private final int sodium; // (mg/1회 제공량) 선택
+ private final int carbohydrate; // (g/1회 제공량) 선택
public NutritionFacts(int servingSize, int servings) {
this(servingSize, servings, 0);
@@ -42,4 +42,4 @@ public static void main(String[] args) {
new NutritionFacts(240, 8, 100, 0, 35, 27);
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter2/item3/enumtype/Elvis.java b/src/effectivejava/chapter2/item3/enumtype/Elvis.java
index b78507e3..e312c0fc 100644
--- a/src/effectivejava/chapter2/item3/enumtype/Elvis.java
+++ b/src/effectivejava/chapter2/item3/enumtype/Elvis.java
@@ -1,14 +1,14 @@
package effectivejava.chapter2.item3.enumtype;
-// Enum singleton - the preferred approach (Page 18)
+// 열거 타입 방식의 싱글턴 - 바람직한 방법 (25쪽)
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() {
- System.out.println("Whoa baby, I'm outta here!");
+ System.out.println("기다려 자기야, 지금 나갈께!");
}
- // This code would normally appear outside the class!
+ // 이 메서드는 보통 클래스 바깥(다른 클래스)에 작성해야 한다!
public static void main(String[] args) {
Elvis elvis = Elvis.INSTANCE;
elvis.leaveTheBuilding();
diff --git a/src/effectivejava/chapter2/item3/field/Elvis.java b/src/effectivejava/chapter2/item3/field/Elvis.java
index d5a3d020..f488e9ef 100644
--- a/src/effectivejava/chapter2/item3/field/Elvis.java
+++ b/src/effectivejava/chapter2/item3/field/Elvis.java
@@ -1,6 +1,6 @@
package effectivejava.chapter2.item3.field;
-// Singleton with public final field (Page 17)
+// 코드 3-1 public static final 필드 방식의 싱글턴 (23쪽)
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
@@ -10,9 +10,9 @@ public void leaveTheBuilding() {
System.out.println("Whoa baby, I'm outta here!");
}
- // This code would normally appear outside the class!
+ // 이 메서드는 보통 클래스 바깥(다른 클래스)에 작성해야 한다!
public static void main(String[] args) {
Elvis elvis = Elvis.INSTANCE;
elvis.leaveTheBuilding();
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter2/item3/staticfactory/Elvis.java b/src/effectivejava/chapter2/item3/staticfactory/Elvis.java
index 1f767166..fdefb456 100644
--- a/src/effectivejava/chapter2/item3/staticfactory/Elvis.java
+++ b/src/effectivejava/chapter2/item3/staticfactory/Elvis.java
@@ -1,6 +1,6 @@
package effectivejava.chapter2.item3.staticfactory;
-// Singleton with static factory (Page 17)
+// 코드 3-2 정적 팩터리 방식의 싱글턴 (24쪽)
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() { }
@@ -10,7 +10,7 @@ public void leaveTheBuilding() {
System.out.println("Whoa baby, I'm outta here!");
}
- // This code would normally appear outside the class!
+ // 이 메서드는 보통 클래스 바깥(다른 클래스)에 작성해야 한다!
public static void main(String[] args) {
Elvis elvis = Elvis.getInstance();
elvis.leaveTheBuilding();
diff --git a/src/effectivejava/chapter2/item4/UtilityClass.java b/src/effectivejava/chapter2/item4/UtilityClass.java
index 2fb40990..5cd7621b 100644
--- a/src/effectivejava/chapter2/item4/UtilityClass.java
+++ b/src/effectivejava/chapter2/item4/UtilityClass.java
@@ -1,11 +1,11 @@
package effectivejava.chapter2.item4;
-// Noninstantiable utility class (Page 19)
+// 코드 4-1 인스턴스를 만들 수 없는 유틸리티 클래스 (26~27쪽)
public class UtilityClass {
- // Suppress default constructor for noninstantiability
+ // 기본 생성자가 만들어지는 것을 막는다(인스턴스화 방지용).
private UtilityClass() {
throw new AssertionError();
}
- // Remainder omitted
+ // 나머지 코드는 생략
}
diff --git a/src/effectivejava/chapter2/item6/RomanNumerals.java b/src/effectivejava/chapter2/item6/RomanNumerals.java
index bf451409..e47275d2 100644
--- a/src/effectivejava/chapter2/item6/RomanNumerals.java
+++ b/src/effectivejava/chapter2/item6/RomanNumerals.java
@@ -1,15 +1,15 @@
package effectivejava.chapter2.item6;
import java.util.regex.Pattern;
-// Reusing expensive object for improved performance (Pages 22 and 23)
+// 값비싼 객체를 재사용해 성능을 개선한다. (32쪽)
public class RomanNumerals {
- // Performance can be greatly improved! (Page 22)
+ // 코드 6-1 성능을 훨씬 더 끌어올릴 수 있다!
static boolean isRomanNumeralSlow(String s) {
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
- // Reusing expensive object for improved performance (Page 23)
+ // 코드 6-2 값비싼 객체를 재사용해 성능을 개선한다.
private static final Pattern ROMAN = Pattern.compile(
"^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
@@ -26,13 +26,14 @@ public static void main(String[] args) {
for (int i = 0; i < numSets; i++) {
long start = System.nanoTime();
for (int j = 0; j < numReps; j++) {
- b ^= isRomanNumeralSlow("MCMLXXVI"); // Change Slow to Fast to see performance difference
+ // 성능 차이를 확인하려면 xxxSlow 메서드를 xxxFast 메서드로 바꿔 실행해보자.
+ b ^= isRomanNumeralSlow("MCMLXXVI");
}
long end = System.nanoTime();
System.out.println(((end - start) / (1_000. * numReps)) + " μs.");
}
- // Prevents VM from optimizing away everything.
+ // VM이 최적화하지 못하게 막는 코드
if (!b)
System.out.println();
}
diff --git a/src/effectivejava/chapter2/item6/Sum.java b/src/effectivejava/chapter2/item6/Sum.java
index 2a7a7ebd..9017a8e3 100644
--- a/src/effectivejava/chapter2/item6/Sum.java
+++ b/src/effectivejava/chapter2/item6/Sum.java
@@ -2,7 +2,7 @@
import java.util.Comparator;
-// Hideously slow program! Can you spot the object creation? (Page 24)
+// 코드 6-3 끔찍이 느리다! 객체가 만들어지는 위치를 찾았는가? (34쪽)
public class Sum {
private static long sum() {
Long sum = 0L;
@@ -22,8 +22,8 @@ public static void main(String[] args) {
System.out.println((end - start) / 1_000_000. + " ms.");
}
- // Prevents VM from optimizing away everything.
+ // VM이 최적화하지 못하게 막는 코드
if (x == 42)
System.out.println();
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter2/item7/EmptyStackException.java b/src/effectivejava/chapter2/item7/EmptyStackException.java
index 8ee2d409..ed4906f4 100644
--- a/src/effectivejava/chapter2/item7/EmptyStackException.java
+++ b/src/effectivejava/chapter2/item7/EmptyStackException.java
@@ -1,5 +1,5 @@
package effectivejava.chapter2.item7;
-// (Thrown by Stack program on Page 26)
+// (36쪽의 Stack 코드에서 던지는 예외)
public class EmptyStackException extends IllegalStateException {
}
diff --git a/src/effectivejava/chapter2/item7/Stack.java b/src/effectivejava/chapter2/item7/Stack.java
index d27d83d6..62a74716 100644
--- a/src/effectivejava/chapter2/item7/Stack.java
+++ b/src/effectivejava/chapter2/item7/Stack.java
@@ -1,7 +1,7 @@
package effectivejava.chapter2.item7;
import java.util.*;
-// Can you spot the "memory leak"? (Pages 26-27)
+// 코드 7-1 메모리 누수가 일어나는 위치는 어디인가? (36쪽)
public class Stack {
private Object[] elements;
private int size = 0;
@@ -23,20 +23,20 @@ public Object pop() {
}
/**
- * Ensure space for at least one more element, roughly
- * doubling the capacity each time the array needs to grow.
+ * 원소를 위한 공간을 적어도 하나 이상 확보한다.
+ * 배열 크기를 늘려야 할 때마다 대략 두 배씩 늘린다.
*/
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
-// // Corrected version of pop method (Page 27)
+// // 코드 7-2 제대로 구현한 pop 메서드 (37쪽)
// public Object pop() {
// if (size == 0)
// throw new EmptyStackException();
// Object result = elements[--size];
-// elements[size] = null; // Eliminate obsolete reference
+// elements[size] = null; // 다 쓴 참조 해제
// return result;
// }
diff --git a/src/effectivejava/chapter2/item8/Adult.java b/src/effectivejava/chapter2/item8/Adult.java
index 9f71f762..722e057c 100644
--- a/src/effectivejava/chapter2/item8/Adult.java
+++ b/src/effectivejava/chapter2/item8/Adult.java
@@ -1,10 +1,10 @@
package effectivejava.chapter2.item8;
-// Well-behaved client of resource with cleaner safety-net (Page 33)
+// cleaner 안전망을 갖춘 자원을 제대로 활용하는 클라이언트 (45쪽)
public class Adult {
public static void main(String[] args) {
try (Room myRoom = new Room(7)) {
- System.out.println("Goodbye");
+ System.out.println("안녕~");
}
}
}
diff --git a/src/effectivejava/chapter2/item8/Room.java b/src/effectivejava/chapter2/item8/Room.java
index a52a2d45..486552ef 100644
--- a/src/effectivejava/chapter2/item8/Room.java
+++ b/src/effectivejava/chapter2/item8/Room.java
@@ -2,11 +2,11 @@
import java.lang.ref.Cleaner;
-// An autocloseable class using a cleaner as a safety net (Page 32)
+// 코드 8-1 cleaner를 안전망으로 활용하는 AutoCloseable 클래스 (44쪽)
public class Room implements AutoCloseable {
private static final Cleaner cleaner = Cleaner.create();
- // Resource that requires cleaning. Must not refer to Room!
+ // 청소가 필요한 자원. 절대 Room을 참조해서는 안 된다!
private static class State implements Runnable {
int numJunkPiles; // Number of junk piles in this room
@@ -14,17 +14,17 @@ private static class State implements Runnable {
this.numJunkPiles = numJunkPiles;
}
- // Invoked by close method or cleaner
+ // close 메서드나 cleaner가 호출한다.
@Override public void run() {
System.out.println("Cleaning room");
numJunkPiles = 0;
}
}
- // The state of this room, shared with our cleanable
+ // 방의 상태. cleanable과 공유한다.
private final State state;
- // Our cleanable. Cleans the room when it’s eligible for gc
+ // cleanable 객체. 수거 대상이 되면 방을 청소한다.
private final Cleaner.Cleanable cleanable;
public Room(int numJunkPiles) {
diff --git a/src/effectivejava/chapter2/item8/Teenager.java b/src/effectivejava/chapter2/item8/Teenager.java
index 28d080ce..e67f8c2f 100644
--- a/src/effectivejava/chapter2/item8/Teenager.java
+++ b/src/effectivejava/chapter2/item8/Teenager.java
@@ -2,13 +2,14 @@
import java.util.concurrent.TimeUnit;
-// Ill-behaved client of resource with cleaner safety-net (Page 33)
+// cleaner 안전망을 갖춘 자원을 제대로 활용하지 못하는 클라이언트 (45쪽)
public class Teenager {
public static void main(String[] args) {
new Room(99);
System.out.println("Peace out");
- // Uncomment next line and retest behavior, but note that you MUST NOT depend on this behavior!
+ // 다음 줄의 주석을 해제한 후 동작을 다시 확인해보자.
+ // 단, 가비지 컬렉러를 강제로 호출하는 이런 방식에 의존해서는 절대 안 된다!
// System.gc();
}
}
diff --git a/src/effectivejava/chapter2/item9/tryfinally/Copy.java b/src/effectivejava/chapter2/item9/tryfinally/Copy.java
index 19b2e469..35b29bdf 100644
--- a/src/effectivejava/chapter2/item9/tryfinally/Copy.java
+++ b/src/effectivejava/chapter2/item9/tryfinally/Copy.java
@@ -5,7 +5,7 @@
public class Copy {
private static final int BUFFER_SIZE = 8 * 1024;
- // try-finally is ugly when used with more than one resource! (Page 34)
+ // 코드 9-2 자원이 둘 이상이면 try-finally 방식은 너무 지저분하다! (47쪽)
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
diff --git a/src/effectivejava/chapter2/item9/tryfinally/TopLine.java b/src/effectivejava/chapter2/item9/tryfinally/TopLine.java
index deb5a73f..0e23fb23 100644
--- a/src/effectivejava/chapter2/item9/tryfinally/TopLine.java
+++ b/src/effectivejava/chapter2/item9/tryfinally/TopLine.java
@@ -5,7 +5,7 @@
import java.io.IOException;
public class TopLine {
- // try-finally - No longer the best way to close resources! (page 34)
+ // 코드 9-1 try-finally - 더 이상 자원을 회수하는 최선의 방책이 아니다! (47쪽)
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
diff --git a/src/effectivejava/chapter2/item9/trywithresources/Copy.java b/src/effectivejava/chapter2/item9/trywithresources/Copy.java
index 15a77dfb..3ea838f9 100644
--- a/src/effectivejava/chapter2/item9/trywithresources/Copy.java
+++ b/src/effectivejava/chapter2/item9/trywithresources/Copy.java
@@ -5,7 +5,7 @@
public class Copy {
private static final int BUFFER_SIZE = 8 * 1024;
- // try-with-resources on multiple resources - short and sweet (Page 35)
+ // 코드 9-4 복수의 자원을 처리하는 try-with-resources - 짧고 매혹적이다! (49쪽)
static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
diff --git a/src/effectivejava/chapter2/item9/trywithresources/TopLine.java b/src/effectivejava/chapter2/item9/trywithresources/TopLine.java
index ea714ac7..35be6fe3 100644
--- a/src/effectivejava/chapter2/item9/trywithresources/TopLine.java
+++ b/src/effectivejava/chapter2/item9/trywithresources/TopLine.java
@@ -6,7 +6,7 @@
import java.io.IOException;
public class TopLine {
- // try-with-resources - the the best way to close resources! (Page 35)
+ // 코드 9-3 try-with-resources - 자원을 회수하는 최선책! (48쪽)
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
diff --git a/src/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java b/src/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java
index f51334c0..2c3fbbde 100644
--- a/src/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java
+++ b/src/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java
@@ -6,7 +6,7 @@
import java.io.IOException;
public class TopLineWithDefault {
- // try-with-resources with a catch clause (Page 36)
+ // 코드 9-5 try-with-resources를 catch 절과 함께 쓰는 모습 (49쪽)
static String firstLineOfFile(String path, String defaultVal) {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
diff --git a/src/effectivejava/chapter3/item10/CaseInsensitiveString.java b/src/effectivejava/chapter3/item10/CaseInsensitiveString.java
index dcb0c228..10f6d37a 100644
--- a/src/effectivejava/chapter3/item10/CaseInsensitiveString.java
+++ b/src/effectivejava/chapter3/item10/CaseInsensitiveString.java
@@ -4,7 +4,7 @@
import java.util.List;
import java.util.Objects;
-// Broken - violates symmetry! (Page 39)
+// 코드 10-1 잘못된 코드 - 대칭성 위배! (54-55쪽)
public final class CaseInsensitiveString {
private final String s;
@@ -12,17 +12,17 @@ public CaseInsensitiveString(String s) {
this.s = Objects.requireNonNull(s);
}
- // Broken - violates symmetry!
+ // 대칭성 위배!
@Override public boolean equals(Object o) {
if (o instanceof CaseInsensitiveString)
return s.equalsIgnoreCase(
((CaseInsensitiveString) o).s);
- if (o instanceof String) // One-way interoperability!
+ if (o instanceof String) // 한 방향으로만 작동한다!
return s.equalsIgnoreCase((String) o);
return false;
}
- // Demonstration of the problem (Page 40)
+ // 문제 시연 (55쪽)
public static void main(String[] args) {
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
@@ -33,7 +33,7 @@ public static void main(String[] args) {
System.out.println(list.contains(s));
}
-// // Fixed equals method (Page 40)
+// // 수정한 equals 메서드 (56쪽)
// @Override public boolean equals(Object o) {
// return o instanceof CaseInsensitiveString &&
// ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
diff --git a/src/effectivejava/chapter3/item10/PhoneNumber.java b/src/effectivejava/chapter3/item10/PhoneNumber.java
index 244d78f6..91733e3a 100644
--- a/src/effectivejava/chapter3/item10/PhoneNumber.java
+++ b/src/effectivejava/chapter3/item10/PhoneNumber.java
@@ -1,13 +1,13 @@
package effectivejava.chapter3.item10;
-// Class with a typical equals method (Page 48)
+// 코드 10-6 전형적인 equals 메서드의 예 (64쪽)
public final class PhoneNumber {
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum) {
- this.areaCode = rangeCheck(areaCode, 999, "area code");
- this.prefix = rangeCheck(prefix, 999, "prefix");
- this.lineNum = rangeCheck(lineNum, 9999, "line num");
+ this.areaCode = rangeCheck(areaCode, 999, "지역코드");
+ this.prefix = rangeCheck(prefix, 999, "프리픽스");
+ this.lineNum = rangeCheck(lineNum, 9999, "가입자 번호");
}
private static short rangeCheck(int val, int max, String arg) {
@@ -26,5 +26,5 @@ private static short rangeCheck(int val, int max, String arg) {
&& pn.areaCode == areaCode;
}
- // Remainder omitted - note that hashCode is REQUIRED (Item 11)!
+ // 나머지 코드는 생략 - hashCode 메서드는 꼭 필요하다(아이템 11)!
}
diff --git a/src/effectivejava/chapter3/item10/Point.java b/src/effectivejava/chapter3/item10/Point.java
index d3acd2e9..9e78a58d 100644
--- a/src/effectivejava/chapter3/item10/Point.java
+++ b/src/effectivejava/chapter3/item10/Point.java
@@ -1,6 +1,6 @@
package effectivejava.chapter3.item10;
-// Simple immutable two-dimensional integer point class (Page 37)
+// 단순한 불변 2차원 정수 점(point) 클래스 (56쪽)
public class Point {
private final int x;
private final int y;
@@ -17,7 +17,7 @@ public Point(int x, int y) {
return p.x == x && p.y == y;
}
-// // Broken - violates Liskov substitution principle (page 43)
+// // 잘못된 코드 - 리스코프 치환 원칙 위배! (59쪽)
// @Override public boolean equals(Object o) {
// if (o == null || o.getClass() != getClass())
// return false;
@@ -25,7 +25,7 @@ public Point(int x, int y) {
// return p.x == x && p.y == y;
// }
- // See Item 11
+ // 아이템 11 참조
@Override public int hashCode() {
return 31 * x + y;
}
diff --git a/src/effectivejava/chapter3/item10/composition/ColorPoint.java b/src/effectivejava/chapter3/item10/composition/ColorPoint.java
index 7bcf2bc2..d29003cf 100644
--- a/src/effectivejava/chapter3/item10/composition/ColorPoint.java
+++ b/src/effectivejava/chapter3/item10/composition/ColorPoint.java
@@ -5,7 +5,7 @@
import java.util.Objects;
-// Adds a value component without violating the equals contract (page 44)
+// 코드 10-5 equals 규약을 지키면서 값 추가하기 (60쪽)
public class ColorPoint {
private final Point point;
private final Color color;
@@ -16,7 +16,7 @@ public ColorPoint(int x, int y, Color color) {
}
/**
- * Returns the point-view of this color point.
+ * 이 ColorPoint의 Point 뷰를 반환한다.
*/
public Point asPoint() {
return point;
@@ -32,4 +32,4 @@ public Point asPoint() {
@Override public int hashCode() {
return 31 * point.hashCode() + color.hashCode();
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter3/item10/inheritance/ColorPoint.java b/src/effectivejava/chapter3/item10/inheritance/ColorPoint.java
index 5aa30419..59868821 100644
--- a/src/effectivejava/chapter3/item10/inheritance/ColorPoint.java
+++ b/src/effectivejava/chapter3/item10/inheritance/ColorPoint.java
@@ -3,7 +3,7 @@
import effectivejava.chapter3.item10.Color;
import effectivejava.chapter3.item10.Point;
-// Attempting to add a value component to Point (Page 41)
+// Point에 값 컴포넌트(color)를 추가 (56쪽)
public class ColorPoint extends Point {
private final Color color;
@@ -12,33 +12,33 @@ public ColorPoint(int x, int y, Color color) {
this.color = color;
}
- // Broken - violates symmetry! (Page 41)
+ // 코드 10-2 잘못된 코드 - 대칭성 위배! (57쪽)
@Override public boolean equals(Object o) {
if (!(o instanceof ColorPoint))
return false;
return super.equals(o) && ((ColorPoint) o).color == color;
}
-// // Broken - violates transitivity! (page 42)
+// // 코드 10-3 잘못된 코드 - 추이성 위배! (57쪽)
// @Override public boolean equals(Object o) {
// if (!(o instanceof Point))
// return false;
//
-// // If o is a normal Point, do a color-blind comparison
+// // o가 일반 Point면 색상을 무시하고 비교한다.
// if (!(o instanceof ColorPoint))
// return o.equals(this);
//
-// // o is a ColorPoint; do a full comparison
+// // o가 ColorPoint면 색상까지 비교한다.
// return super.equals(o) && ((ColorPoint) o).color == color;
// }
public static void main(String[] args) {
- // First equals function violates symmetry (Page 42)
+ // 첫 번째 equals 메서드(코드 10-2)는 대칭성을 위배한다. (57쪽)
Point p = new Point(1, 2);
ColorPoint cp = new ColorPoint(1, 2, Color.RED);
System.out.println(p.equals(cp) + " " + cp.equals(p));
- // Second equals function violates transitivity (Page 42)
+ // 두 번째 equals 메서드(코드 10-3)는 추이성을 위배한다. (57쪽)
ColorPoint p1 = new ColorPoint(1, 2, Color.RED);
Point p2 = new Point(1, 2);
ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE);
diff --git a/src/effectivejava/chapter3/item10/inheritance/CounterPoint.java b/src/effectivejava/chapter3/item10/inheritance/CounterPoint.java
index 74771dbe..9a1900e6 100644
--- a/src/effectivejava/chapter3/item10/inheritance/CounterPoint.java
+++ b/src/effectivejava/chapter3/item10/inheritance/CounterPoint.java
@@ -3,7 +3,7 @@
import java.util.concurrent.atomic.*;
-// Trivial subclass of Point - doesn't add a value component (Page 43)
+// Point의 평범한 하위 클래스 - 값 컴포넌트를 추가하지 않았다. (59쪽)
public class CounterPoint extends Point {
private static final AtomicInteger counter =
new AtomicInteger();
diff --git a/src/effectivejava/chapter3/item10/inheritance/CounterPointTest.java b/src/effectivejava/chapter3/item10/inheritance/CounterPointTest.java
index 7e72d262..a0a1339b 100644
--- a/src/effectivejava/chapter3/item10/inheritance/CounterPointTest.java
+++ b/src/effectivejava/chapter3/item10/inheritance/CounterPointTest.java
@@ -3,9 +3,9 @@
import java.util.*;
-// Test program that uses CounterPoint as Point
+// CounterPoint를 Point로 사용하는 테스트 프로그램
public class CounterPointTest {
- // Initialize unitCircle to contain all Points on the unit circle (Page 43)
+ // 단위 원 안의 모든 점을 포함하도록 unitCircle을 초기화한다. (58쪽)
private static final Set unitCircle = Set.of(
new Point( 1, 0), new Point( 0, 1),
new Point(-1, 0), new Point( 0, -1));
@@ -18,10 +18,10 @@ public static void main(String[] args) {
Point p1 = new Point(1, 0);
Point p2 = new CounterPoint(1, 0);
- // Prints true
+ // true를 출력한다.
System.out.println(onUnitCircle(p1));
- // Should print true, but doesn't if Point uses getClass-based equals
+ // true를 출력해야 하지만, Point의 equals가 getClass를 사용해 작성되었다면 그렇지 않다.
System.out.println(onUnitCircle(p2));
}
}
diff --git a/src/effectivejava/chapter3/item11/PhoneNumber.java b/src/effectivejava/chapter3/item11/PhoneNumber.java
index 084f1e95..0273865e 100644
--- a/src/effectivejava/chapter3/item11/PhoneNumber.java
+++ b/src/effectivejava/chapter3/item11/PhoneNumber.java
@@ -1,7 +1,7 @@
package effectivejava.chapter3.item11;
import java.util.*;
-// Shows the need for overriding hashcode when you override equals (Pages 50-53 )
+// equals를 재정의하면 hashCode로 재정의해야 함을 보여준다. (70-71쪽)
public final class PhoneNumber {
private final short areaCode, prefix, lineNum;
@@ -28,9 +28,9 @@ private static short rangeCheck(int val, int max, String arg) {
}
- // Broken with no hashCode; works with any of the three below
+ // hashCode 없이는 제대로 동작하지 않는다. 다음 셋 중 하나를 활성화하자.
-// // Typical hashCode method (Page 52)
+// // 코드 11-2 전형적인 hashCode 메서드 (70쪽)
// @Override public int hashCode() {
// int result = Short.hashCode(areaCode);
// result = 31 * result + Short.hashCode(prefix);
@@ -38,13 +38,13 @@ private static short rangeCheck(int val, int max, String arg) {
// return result;
// }
-// // One-line hashCode method - mediocre performance (page 53)
+// // 코드 11-3 한 줄짜리 hashCode 메서드 - 성능이 살짝 아쉽다. (71쪽)
// @Override public int hashCode() {
// return Objects.hash(lineNum, prefix, areaCode);
// }
-// // hashCode method with lazily initialized cached hash code (page 53)
-// private int hashCode; // Automatically initialized to 0
+// // 해시코드를 지연 초기화하는 hashCode 메서드 - 스레드 안정성까지 고려해야 한다. (71쪽)
+// private int hashCode; // 자동으로 0으로 초기화된다.
//
// @Override public int hashCode() {
// int result = hashCode;
@@ -59,7 +59,7 @@ private static short rangeCheck(int val, int max, String arg) {
public static void main(String[] args) {
Map m = new HashMap<>();
- m.put(new PhoneNumber(707, 867, 5309), "Jenny");
+ m.put(new PhoneNumber(707, 867, 5309), "제니");
System.out.println(m.get(new PhoneNumber(707, 867, 5309)));
}
}
diff --git a/src/effectivejava/chapter3/item12/PhoneNumber.java b/src/effectivejava/chapter3/item12/PhoneNumber.java
index ccc3206c..45eee1ba 100644
--- a/src/effectivejava/chapter3/item12/PhoneNumber.java
+++ b/src/effectivejava/chapter3/item12/PhoneNumber.java
@@ -1,13 +1,13 @@
package effectivejava.chapter3.item12;
-// Adding a toString method to PhoneNumber (page 52)
+// PhoneNumber에 toString 메서드 추가 (75쪽)
public final class PhoneNumber {
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum) {
- this.areaCode = rangeCheck(areaCode, 999, "area code");
- this.prefix = rangeCheck(prefix, 999, "prefix");
- this.lineNum = rangeCheck(lineNum, 9999, "line num");
+ this.areaCode = rangeCheck(areaCode, 999, "지역코드");
+ this.prefix = rangeCheck(prefix, 999, "프리픽스");
+ this.lineNum = rangeCheck(lineNum, 9999, "가입자 번호");
}
private static short rangeCheck(int val, int max, String arg) {
@@ -34,16 +34,14 @@ private static short rangeCheck(int val, int max, String arg) {
}
/**
- * Returns the string representation of this phone number.
- * The string consists of twelve characters whose format is
- * "XXX-YYY-ZZZZ", where XXX is the area code, YYY is the
- * prefix, and ZZZZ is the line number. Each of the capital
- * letters represents a single decimal digit.
+ * 이 전화번호의 문자열 표현을 반환한다.
+ * 이 문자열은 "XXX-YYY-ZZZZ" 형태의 12글자로 구성된다.
+ * XXX는 지역 코드, YYY는 프리픽스, ZZZZ는 가입자 번호다.
+ * 각각의 대문자는 10진수 숫자 하나를 나타낸다.
*
- * If any of the three parts of this phone number is too small
- * to fill up its field, the field is padded with leading zeros.
- * For example, if the value of the line number is 123, the last
- * four characters of the string representation will be "0123".
+ * 전화번호의 각 부분의 값이 너무 작아서 자릿수를 채울 수 없다면,
+ * 앞에서부터 0으로 채워나간다. 예컨대 가입자 번호가 123이라면
+ * 전화번호의 마지막 네 문자는 "0123"이 된다.
*/
// @Override public String toString() {
// return String.format("%03d-%03d-%04d",
@@ -52,6 +50,6 @@ private static short rangeCheck(int val, int max, String arg) {
public static void main(String[] args) {
PhoneNumber jenny = new PhoneNumber(707, 867, 5309);
- System.out.println("Jenny's number: " + jenny);
+ System.out.println("제니의 번호: " + jenny);
}
}
diff --git a/src/effectivejava/chapter3/item13/PhoneNumber.java b/src/effectivejava/chapter3/item13/PhoneNumber.java
index 27b3b4c6..cddd9200 100644
--- a/src/effectivejava/chapter3/item13/PhoneNumber.java
+++ b/src/effectivejava/chapter3/item13/PhoneNumber.java
@@ -3,14 +3,14 @@
import java.util.HashMap;
import java.util.Map;
-// Adding a clone method to PhoneNumber (page 59)
+// PhoneNumber에 clone 메서드 추가 (79쪽)
public final class PhoneNumber implements Cloneable {
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum) {
- this.areaCode = rangeCheck(areaCode, 999, "area code");
- this.prefix = rangeCheck(prefix, 999, "prefix");
- this.lineNum = rangeCheck(lineNum, 9999, "line num");
+ this.areaCode = rangeCheck(areaCode, 999, "지역코드");
+ this.prefix = rangeCheck(prefix, 999, "프리픽스");
+ this.lineNum = rangeCheck(lineNum, 9999, "가입자 번호");
}
private static short rangeCheck(int val, int max, String arg) {
@@ -37,35 +37,33 @@ private static short rangeCheck(int val, int max, String arg) {
}
/**
- * Returns the string representation of this phone number.
- * The string consists of twelve characters whose format is
- * "XXX-YYY-ZZZZ", where XXX is the area code, YYY is the
- * prefix, and ZZZZ is the line number. Each of the capital
- * letters represents a single decimal digit.
+ * 이 전화번호의 문자열 표현을 반환한다.
+ * 이 문자열은 "XXX-YYY-ZZZZ" 형태의 12글자로 구성된다.
+ * XXX는 지역 코드, YYY는 프리픽스, ZZZZ는 가입자 번호다.
+ * 각각의 대문자는 10진수 숫자 하나를 나타낸다.
*
- * If any of the three parts of this phone number is too small
- * to fill up its field, the field is padded with leading zeros.
- * For example, if the value of the line number is 123, the last
- * four characters of the string representation will be "0123".
+ * 전화번호의 각 부분의 값이 너무 작아서 자릿수를 채울 수 없다면,
+ * 앞에서부터 0으로 채워나간다. 예컨대 가입자 번호가 123이라면
+ * 전화번호의 마지막 네 문자는 "0123"이 된다.
*/
@Override public String toString() {
return String.format("%03d-%03d-%04d",
areaCode, prefix, lineNum);
}
- // Clone method for class with no references to mutable state (Page 59)
+ // 코드 13-1 가변 상태를 참조하지 않는 클래스용 clone 메서드 (79쪽)
@Override public PhoneNumber clone() {
try {
return (PhoneNumber) super.clone();
} catch (CloneNotSupportedException e) {
- throw new AssertionError(); // Can't happen
+ throw new AssertionError(); // 일어날 수 없는 일이다.
}
}
public static void main(String[] args) {
PhoneNumber pn = new PhoneNumber(707, 867, 5309);
Map m = new HashMap<>();
- m.put(pn, "Jenny");
+ m.put(pn, "제니");
System.out.println(m.get(pn.clone()));
}
}
diff --git a/src/effectivejava/chapter3/item13/Stack.java b/src/effectivejava/chapter3/item13/Stack.java
index 1c49e014..a9fa71d8 100644
--- a/src/effectivejava/chapter3/item13/Stack.java
+++ b/src/effectivejava/chapter3/item13/Stack.java
@@ -1,7 +1,7 @@
package effectivejava.chapter3.item13;
import java.util.Arrays;
-// A cloneable version of Stack (Pages 60-61)
+// Stack의 복제 가능 버전 (80-81쪽)
public class Stack implements Cloneable {
private Object[] elements;
private int size = 0;
@@ -20,7 +20,7 @@ public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
- elements[size] = null; // Eliminate obsolete reference
+ elements[size] = null; // 다 쓴 참조 해제
return result;
}
@@ -28,7 +28,7 @@ public boolean isEmpty() {
return size ==0;
}
- // Clone method for class with references to mutable state
+ // 코드 13-2 가변 상태를 참조하는 클래스용 clone 메서드
@Override public Stack clone() {
try {
Stack result = (Stack) super.clone();
@@ -39,13 +39,13 @@ public boolean isEmpty() {
}
}
- // Ensure space for at least one more element.
+ // 원소를 위한 공간을 적어도 하나 이상 확보한다.
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
- // To see that clone works, call with several command line arguments
+ // clone이 동작하는 모습을 보려면 명령줄 인수를 몇 개 덧붙여서 호출해야 한다.
public static void main(String[] args) {
Stack stack = new Stack();
for (String arg : args)
diff --git a/src/effectivejava/chapter3/item14/CaseInsensitiveString.java b/src/effectivejava/chapter3/item14/CaseInsensitiveString.java
index 9304ad19..82f9b6ea 100644
--- a/src/effectivejava/chapter3/item14/CaseInsensitiveString.java
+++ b/src/effectivejava/chapter3/item14/CaseInsensitiveString.java
@@ -2,7 +2,7 @@
import java.util.*;
-// Single-field Comparable with object reference field (Page 69)
+// 코드 14-1 객체 참조 필드가 하나뿐인 비교자 (90쪽)
public final class CaseInsensitiveString
implements Comparable {
private final String s;
@@ -11,7 +11,7 @@ public CaseInsensitiveString(String s) {
this.s = Objects.requireNonNull(s);
}
- // Fixed equals method (Page 40)
+ // 수정된 equals 메서드 (56쪽)
@Override public boolean equals(Object o) {
return o instanceof CaseInsensitiveString &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
@@ -25,7 +25,7 @@ public CaseInsensitiveString(String s) {
return s;
}
- // Using an existing comparator to make a class comparable
+ // 자바가 제공하는 비교자를 사용해 클래스를 비교한다.
public int compareTo(CaseInsensitiveString cis) {
return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s);
}
@@ -36,4 +36,4 @@ public static void main(String[] args) {
s.add(new CaseInsensitiveString(arg));
System.out.println(s);
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter3/item14/PhoneNumber.java b/src/effectivejava/chapter3/item14/PhoneNumber.java
index 22d5ee95..d107540d 100644
--- a/src/effectivejava/chapter3/item14/PhoneNumber.java
+++ b/src/effectivejava/chapter3/item14/PhoneNumber.java
@@ -3,14 +3,14 @@
import java.util.concurrent.ThreadLocalRandom;
import static java.util.Comparator.*;
-// Making PhoneNumber comparable (Pages 69-70)
+// PhoneNumber를 비교할 수 있게 만든다. (91-92쪽)
public final class PhoneNumber implements Cloneable, Comparable {
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum) {
- this.areaCode = rangeCheck(areaCode, 999, "area code");
- this.prefix = rangeCheck(prefix, 999, "prefix");
- this.lineNum = rangeCheck(lineNum, 9999, "line num");
+ this.areaCode = rangeCheck(areaCode, 999, "지역코드");
+ this.prefix = rangeCheck(prefix, 999, "프리픽스");
+ this.lineNum = rangeCheck(lineNum, 9999, "가입자 번호");
}
private static short rangeCheck(int val, int max, String arg) {
@@ -37,23 +37,21 @@ private static short rangeCheck(int val, int max, String arg) {
}
/**
- * Returns the string representation of this phone number.
- * The string consists of twelve characters whose format is
- * "XXX-YYY-ZZZZ", where XXX is the area code, YYY is the
- * prefix, and ZZZZ is the line number. Each of the capital
- * letters represents a single decimal digit.
+ * 이 전화번호의 문자열 표현을 반환한다.
+ * 이 문자열은 "XXX-YYY-ZZZZ" 형태의 12글자로 구성된다.
+ * XXX는 지역 코드, YYY는 프리픽스, ZZZZ는 가입자 번호다.
+ * 각각의 대문자는 10진수 숫자 하나를 나타낸다.
*
- * If any of the three parts of this phone number is too small
- * to fill up its field, the field is padded with leading zeros.
- * For example, if the value of the line number is 123, the last
- * four characters of the string representation will be "0123".
+ * 전화번호의 각 부분의 값이 너무 작아서 자릿수를 채울 수 없다면,
+ * 앞에서부터 0으로 채워나간다. 예컨대 가입자 번호가 123이라면
+ * 전화번호의 마지막 네 문자는 "0123"이 된다.
*/
@Override public String toString() {
return String.format("%03d-%03d-%04d",
areaCode, prefix, lineNum);
}
-// // Multiple-field Comparable with primitive fields (page 69)
+// // 코드 14-2 기본 타입 필드가 여럿일 때의 비교자 (91쪽)
// public int compareTo(PhoneNumber pn) {
// int result = Short.compare(areaCode, pn.areaCode);
// if (result == 0) {
@@ -64,7 +62,7 @@ private static short rangeCheck(int val, int max, String arg) {
// return result;
// }
- // Comparable with comparator construction methods (page 70)
+ // 코드 14-3 비교자 생성 메서드를 활용한 비교자 (92쪽)
private static final Comparator COMPARATOR =
comparingInt((PhoneNumber pn) -> pn.areaCode)
.thenComparingInt(pn -> pn.prefix)
diff --git a/src/effectivejava/chapter3/item14/WordList.java b/src/effectivejava/chapter3/item14/WordList.java
index 1ed82e17..f7034ba5 100644
--- a/src/effectivejava/chapter3/item14/WordList.java
+++ b/src/effectivejava/chapter3/item14/WordList.java
@@ -1,7 +1,7 @@
package effectivejava.chapter3.item14;
import java.util.*;
-// The benefits of implementing Comparable (Page 66)
+// Comparable 구현 시의 이점 (87쪽)
public class WordList {
public static void main(String[] args) {
Set s = new TreeSet<>();
diff --git a/src/effectivejava/chapter4/item16/Point.java b/src/effectivejava/chapter4/item16/Point.java
index 9ef9f681..5c9056db 100644
--- a/src/effectivejava/chapter4/item16/Point.java
+++ b/src/effectivejava/chapter4/item16/Point.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item16;
-// Encapsulation of data by accessor methods and mutators (Page 78)
+// 코드 16-2 접근자와 변경자(mutator) 메서드를 활용해 데이터를 캡슐화한다. (102쪽)
class Point {
private double x;
private double y;
diff --git a/src/effectivejava/chapter4/item16/Time.java b/src/effectivejava/chapter4/item16/Time.java
index aabb8055..3c6ee35a 100644
--- a/src/effectivejava/chapter4/item16/Time.java
+++ b/src/effectivejava/chapter4/item16/Time.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item16;
-// Public class with exposed immutable fields - questionable (Page 79)
+// 코드 16-3 불변 필드를 노출한 public 클래스 - 과연 좋은가? (103-104쪽)
public final class Time {
private static final int HOURS_PER_DAY = 24;
private static final int MINUTES_PER_HOUR = 60;
@@ -17,5 +17,5 @@ public Time(int hour, int minute) {
this.minute = minute;
}
- // Remainder omitted
+ // 나머지 코드 생략
}
diff --git a/src/effectivejava/chapter4/item17/Complex.java b/src/effectivejava/chapter4/item17/Complex.java
index 49d33d81..f935b3ae 100644
--- a/src/effectivejava/chapter4/item17/Complex.java
+++ b/src/effectivejava/chapter4/item17/Complex.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item17;
-// Immutable complex number class (Pages 81-82)
+// 코드 17-1 불변 복소수 클래스 (106-107쪽)
public final class Complex {
private final double re;
private final double im;
@@ -21,7 +21,7 @@ public Complex plus(Complex c) {
return new Complex(re + c.re, im + c.im);
}
- // Static factory, used in conjunction with private constructor (Page 85)
+ // 코드 17-2 정적 팩터리(private 생성자와 함께 사용해야 한다.) (110-111쪽)
public static Complex valueOf(double re, double im) {
return new Complex(re, im);
}
@@ -48,7 +48,7 @@ public Complex dividedBy(Complex c) {
return false;
Complex c = (Complex) o;
- // See page 47 to find out why we use compare instead of ==
+ // == 대신 compare를 사용하는 이유는 63쪽을 확인하라.
return Double.compare(c.re, re) == 0
&& Double.compare(c.im, im) == 0;
}
diff --git a/src/effectivejava/chapter4/item18/ForwardingSet.java b/src/effectivejava/chapter4/item18/ForwardingSet.java
index 307822ff..b826959a 100644
--- a/src/effectivejava/chapter4/item18/ForwardingSet.java
+++ b/src/effectivejava/chapter4/item18/ForwardingSet.java
@@ -1,7 +1,7 @@
package effectivejava.chapter4.item18;
import java.util.*;
-// Reusable forwarding class (Page 90)
+// 코드 18-3 재사용할 수 있는 전달 클래스 (118쪽)
public class ForwardingSet implements Set {
private final Set s;
public ForwardingSet(Set s) { this.s = s; }
diff --git a/src/effectivejava/chapter4/item18/InstrumentedHashSet.java b/src/effectivejava/chapter4/item18/InstrumentedHashSet.java
index 7533c7f2..c2e46035 100644
--- a/src/effectivejava/chapter4/item18/InstrumentedHashSet.java
+++ b/src/effectivejava/chapter4/item18/InstrumentedHashSet.java
@@ -1,9 +1,9 @@
package effectivejava.chapter4.item18;
import java.util.*;
-// Broken - Inappropriate use of inheritance! (Page 87)
+// 코드 18-1 잘못된 예 - 상속을 잘못 사용했다! (114쪽)
public class InstrumentedHashSet extends HashSet {
- // The number of attempted element insertions
+ // 추가된 원소의 수
private int addCount = 0;
public InstrumentedHashSet() {
@@ -29,7 +29,7 @@ public int getAddCount() {
public static void main(String[] args) {
InstrumentedHashSet s = new InstrumentedHashSet<>();
- s.addAll(List.of("Snap", "Crackle", "Pop"));
+ s.addAll(List.of("틱", "탁탁", "펑"));
System.out.println(s.getAddCount());
}
}
diff --git a/src/effectivejava/chapter4/item18/InstrumentedSet.java b/src/effectivejava/chapter4/item18/InstrumentedSet.java
index 920fd3f2..29d85a3d 100644
--- a/src/effectivejava/chapter4/item18/InstrumentedSet.java
+++ b/src/effectivejava/chapter4/item18/InstrumentedSet.java
@@ -1,7 +1,7 @@
package effectivejava.chapter4.item18;
import java.util.*;
-// Wrapper class - uses composition in place of inheritance (Page 90)
+// 코드 18-2 래퍼 클래스 - 상속 대신 컴포지션을 사용했다. (117-118쪽)
public class InstrumentedSet extends ForwardingSet {
private int addCount = 0;
@@ -23,7 +23,7 @@ public int getAddCount() {
public static void main(String[] args) {
InstrumentedSet s = new InstrumentedSet<>(new HashSet<>());
- s.addAll(List.of("Snap", "Crackle", "Pop"));
+ s.addAll(List.of("틱", "탁탁", "펑"));
System.out.println(s.getAddCount());
}
}
diff --git a/src/effectivejava/chapter4/item19/Sub.java b/src/effectivejava/chapter4/item19/Sub.java
index 90b9f007..286c7f59 100644
--- a/src/effectivejava/chapter4/item19/Sub.java
+++ b/src/effectivejava/chapter4/item19/Sub.java
@@ -2,16 +2,16 @@
import java.time.Instant;
-// Demonstration of what can go wrong when you override a method called from constructor (Page 96)
+// 생성자에서 호출하는 메서드를 재정의했을 때의 문제를 보여준다. (126쪽)
public final class Sub extends Super {
- // Blank final, set by constructor
+ // 초기화되지 않은 final 필드. 생성자에서 초기화한다.
private final Instant instant;
Sub() {
instant = Instant.now();
}
- // Overriding method invoked by superclass constructor
+ // 재정의 가능 메서드. 상위 클래스의 생성자가 호출한다.
@Override public void overrideMe() {
System.out.println(instant);
}
diff --git a/src/effectivejava/chapter4/item19/Super.java b/src/effectivejava/chapter4/item19/Super.java
index 0235641c..1553b146 100644
--- a/src/effectivejava/chapter4/item19/Super.java
+++ b/src/effectivejava/chapter4/item19/Super.java
@@ -1,8 +1,8 @@
package effectivejava.chapter4.item19;
-// Class whose constructor invokes an overridable method. NEVER DO THIS! (Page 95)
+// 재정의 가능 메서드를 호출하는 생성자 - 따라 하지 말 것! (115쪽)
public class Super {
- // Broken - constructor invokes an overridable method
+ // 잘못된 예 - 생성자가 재정의 가능 메서드를 호출한다.
public Super() {
overrideMe();
}
diff --git a/src/effectivejava/chapter4/item20/AbstractMapEntry.java b/src/effectivejava/chapter4/item20/AbstractMapEntry.java
index 97f4cf44..a4215e0d 100644
--- a/src/effectivejava/chapter4/item20/AbstractMapEntry.java
+++ b/src/effectivejava/chapter4/item20/AbstractMapEntry.java
@@ -1,15 +1,15 @@
package effectivejava.chapter4.item20;
import java.util.*;
-// Skeletal implementation class (Pages 102-3)
+// 코드 20-2 골격 구현 클래스 (134-135쪽)
public abstract class AbstractMapEntry
implements Map.Entry {
- // Entries in a modifiable map must override this method
+ // 변경 가능한 엔트리는 이 메서드를 반드시 재정의해야 한다.
@Override public V setValue(V value) {
throw new UnsupportedOperationException();
}
- // Implements the general contract of Map.Entry.equals
+ // Map.Entry.equals의 일반 규약을 구현한다.
@Override public boolean equals(Object o) {
if (o == this)
return true;
@@ -20,7 +20,7 @@ public abstract class AbstractMapEntry
&& Objects.equals(e.getValue(), getValue());
}
- // Implements the general contract of Map.Entry.hashCode
+ // Map.Entry.hashCode의 일반 규약을 구현한다.
@Override public int hashCode() {
return Objects.hashCode(getKey())
^ Objects.hashCode(getValue());
diff --git a/src/effectivejava/chapter4/item20/IntArrays.java b/src/effectivejava/chapter4/item20/IntArrays.java
index 46a367c4..a2e7a914 100644
--- a/src/effectivejava/chapter4/item20/IntArrays.java
+++ b/src/effectivejava/chapter4/item20/IntArrays.java
@@ -1,22 +1,22 @@
package effectivejava.chapter4.item20;
import java.util.*;
-// Concrete implementation built atop skeletal implementation (Page 101)
+// 코드 20-1 골격 구현을 사용해 완성한 구체 클래스 (133쪽)
public class IntArrays {
static List intArrayAsList(int[] a) {
Objects.requireNonNull(a);
- // The diamond operator is only legal here in Java 9 and later
- // If you're using an earlier release, specify
+ // 다이아몬드 연산자를 이렇게 사용하는 건 자바 9부터 가능하다.
+ // 더 낮은 버전을 사용한다면 로 수정하자.
return new AbstractList<>() {
@Override public Integer get(int i) {
- return a[i]; // Autoboxing (Item 6)
+ return a[i]; // 오토박싱(아이템 6)
}
@Override public Integer set(int i, Integer val) {
int oldVal = a[i];
- a[i] = val; // Auto-unboxing
- return oldVal; // Autoboxing
+ a[i] = val; // 오토언박싱
+ return oldVal; // 오토박싱
}
@Override public int size() {
diff --git a/src/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java b/src/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java
index 5b97d92d..0f2578ef 100644
--- a/src/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java
+++ b/src/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java
@@ -1,13 +1,13 @@
package effectivejava.chapter4.item22.constantinterface;
-// Constant interface antipattern - do not use!
+// 코드 22-1 상수 인터페이스 안티패턴 - 사용금지! (139쪽)
public interface PhysicalConstants {
- // Avogadro's number (1/mol)
+ // 아보가드로 수 (1/몰)
static final double AVOGADROS_NUMBER = 6.022_140_857e23;
- // Boltzmann constant (J/K)
+ // 볼츠만 상수 (J/K)
static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23;
- // Mass of the electron (kg)
+ // 전자 질량 (kg)
static final double ELECTRON_MASS = 9.109_383_56e-31;
}
diff --git a/src/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java b/src/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java
index a27954f1..a4871147 100644
--- a/src/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java
+++ b/src/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java
@@ -1,15 +1,15 @@
package effectivejava.chapter4.item22.constantutilityclass;
-// Constant utility class (Page 108)
+// 코드 22-2 상수 유틸리티 클래스 (140쪽)
public class PhysicalConstants {
- private PhysicalConstants() { } // Prevents instantiation
+ private PhysicalConstants() { } // 인스턴스화 방지
- // Avogadro's number (1/mol)
+ // 아보가드로 수 (1/몰)
public static final double AVOGADROS_NUMBER = 6.022_140_857e23;
- // Boltzmann constant (J/K)
+ // 볼츠만 상수 (J/K)
public static final double BOLTZMANN_CONST = 1.380_648_52e-23;
- // Mass of the electron (kg)
+ // 전자 질량 (kg)
public static final double ELECTRON_MASS = 9.109_383_56e-31;
}
diff --git a/src/effectivejava/chapter4/item23/hierarchy/Circle.java b/src/effectivejava/chapter4/item23/hierarchy/Circle.java
index 6b7017a5..0702ed56 100644
--- a/src/effectivejava/chapter4/item23/hierarchy/Circle.java
+++ b/src/effectivejava/chapter4/item23/hierarchy/Circle.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item23.hierarchy;
-// Class hierarchy replacement for a tagged class (Page 110-11)
+// 코드 23-2 태그 달린 클래스를 클래스 계층구조로 변환 (144쪽)
class Circle extends Figure {
final double radius;
diff --git a/src/effectivejava/chapter4/item23/hierarchy/Figure.java b/src/effectivejava/chapter4/item23/hierarchy/Figure.java
index 1ab39fa0..23f6f842 100644
--- a/src/effectivejava/chapter4/item23/hierarchy/Figure.java
+++ b/src/effectivejava/chapter4/item23/hierarchy/Figure.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item23.hierarchy;
-// Class hierarchy replacement for a tagged class (Page 110-11)
+// 코드 23-2 태그 달린 클래스를 클래스 계층구조로 변환 (144쪽)
abstract class Figure {
abstract double area();
}
diff --git a/src/effectivejava/chapter4/item23/hierarchy/Rectangle.java b/src/effectivejava/chapter4/item23/hierarchy/Rectangle.java
index 090ed053..c5eee8f4 100644
--- a/src/effectivejava/chapter4/item23/hierarchy/Rectangle.java
+++ b/src/effectivejava/chapter4/item23/hierarchy/Rectangle.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item23.hierarchy;
-// Class hierarchy replacement for a tagged class (Page 110-11)
+// 코드 23-2 태그 달린 클래스를 클래스 계층구조로 변환 (144쪽)
class Rectangle extends Figure {
final double length;
final double width;
@@ -10,4 +10,4 @@ class Rectangle extends Figure {
this.width = width;
}
@Override double area() { return length * width; }
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter4/item23/hierarchy/Square.java b/src/effectivejava/chapter4/item23/hierarchy/Square.java
index 713f448d..2a2694cb 100644
--- a/src/effectivejava/chapter4/item23/hierarchy/Square.java
+++ b/src/effectivejava/chapter4/item23/hierarchy/Square.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item23.hierarchy;
-// Class hierarchy replacement for a tagged class (Page 110-11)
+// 태그 달린 클래스를 클래스 계층구조로 변환 (145쪽)
class Square extends Rectangle {
Square(double side) {
super(side, side);
diff --git a/src/effectivejava/chapter4/item23/taggedclass/Figure.java b/src/effectivejava/chapter4/item23/taggedclass/Figure.java
index efb7b789..e466933d 100644
--- a/src/effectivejava/chapter4/item23/taggedclass/Figure.java
+++ b/src/effectivejava/chapter4/item23/taggedclass/Figure.java
@@ -1,26 +1,26 @@
package effectivejava.chapter4.item23.taggedclass;
-// Tagged class - vastly inferior to a class hierarchy! (Page 109)
+// 코드 23-1 태그 달린 클래스 - 클래스 계층구조보다 훨씬 나쁘다! (142-143쪽)
class Figure {
enum Shape { RECTANGLE, CIRCLE };
- // Tag field - the shape of this figure
+ // 태그 필드 - 현재 모양을 나타낸다.
final Shape shape;
- // These fields are used only if shape is RECTANGLE
+ // 다음 필드들은 모양이 사각형(RECTANGLE)일 때만 쓰인다.
double length;
double width;
- // This field is used only if shape is CIRCLE
+ // 다음 필드는 모양이 원(CIRCLE)일 때만 쓰인다.
double radius;
- // Constructor for circle
+ // 원용 생성자
Figure(double radius) {
shape = Shape.CIRCLE;
this.radius = radius;
}
- // Constructor for rectangle
+ // 사각형용 생성자
Figure(double length, double width) {
shape = Shape.RECTANGLE;
this.length = length;
diff --git a/src/effectivejava/chapter4/item25/Dessert.java b/src/effectivejava/chapter4/item25/Dessert.java
index 0b6536e0..4921cce8 100644
--- a/src/effectivejava/chapter4/item25/Dessert.java
+++ b/src/effectivejava/chapter4/item25/Dessert.java
@@ -1,10 +1,10 @@
package effectivejava.chapter4.item25;
-// Two classes defined in one file. Don't ever do this! (Page 115)
+// 코드 25-2 두 클래스가 한 파일(Dessert.java)에 정의되었다. - 따라 하지 말 것! (151쪽)
//class Utensil {
// static final String NAME = "pot";
//}
//
//class Dessert {
// static final String NAME = "pie";
-//}
\ No newline at end of file
+//}
diff --git a/src/effectivejava/chapter4/item25/Main.java b/src/effectivejava/chapter4/item25/Main.java
index b48aa364..e5c12888 100644
--- a/src/effectivejava/chapter4/item25/Main.java
+++ b/src/effectivejava/chapter4/item25/Main.java
@@ -1,8 +1,8 @@
package effectivejava.chapter4.item25;
-// (Page 115)
+// (150쪽)
public class Main {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME);
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter4/item25/Test.java b/src/effectivejava/chapter4/item25/Test.java
index 710aad57..35d210ef 100644
--- a/src/effectivejava/chapter4/item25/Test.java
+++ b/src/effectivejava/chapter4/item25/Test.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item25;
-// Static member classes instead of multiple top-level classes (Page 116)
+// 코드 25-3 톱레벨 클래스들을 정적 멤버 클래스로 바꿔본 모습 (151-152쪽)
public class Test {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME);
diff --git a/src/effectivejava/chapter4/item25/Utensil.java b/src/effectivejava/chapter4/item25/Utensil.java
index dbb13bd6..936640b1 100644
--- a/src/effectivejava/chapter4/item25/Utensil.java
+++ b/src/effectivejava/chapter4/item25/Utensil.java
@@ -1,6 +1,6 @@
package effectivejava.chapter4.item25;
-// Two classes defined in one file. Don't ever do this! (Page 115)
+// 코드 25-1 두 클래스가 한 파일(Utensil.java)에 정의되었다. - 따라 하지 말 것! (150쪽)
class Utensil {
static final String NAME = "pan";
}
diff --git a/src/effectivejava/chapter5/item26/Raw.java b/src/effectivejava/chapter5/item26/Raw.java
index 5cb1d909..5b492b2d 100644
--- a/src/effectivejava/chapter5/item26/Raw.java
+++ b/src/effectivejava/chapter5/item26/Raw.java
@@ -1,12 +1,12 @@
package effectivejava.chapter5.item26;
import java.util.*;
-// Fails at runtime - unsafeAdd method uses a raw type (List)! (Page 119)
+// 코드 26-4 런타임에 실패한다. - unsafeAdd 메서드가 로 타입(List)을 사용 (156-157쪽)
public class Raw {
public static void main(String[] args) {
List strings = new ArrayList<>();
unsafeAdd(strings, Integer.valueOf(42));
- String s = strings.get(0); // Has compiler-generated cast
+ String s = strings.get(0); // 컴파일러가 자동으로 형변환 코드를 넣어준다.
}
private static void unsafeAdd(List list, Object o) {
diff --git a/src/effectivejava/chapter5/item28/Chooser.java b/src/effectivejava/chapter5/item28/Chooser.java
index 259ab264..bf1dbd98 100644
--- a/src/effectivejava/chapter5/item28/Chooser.java
+++ b/src/effectivejava/chapter5/item28/Chooser.java
@@ -6,7 +6,7 @@
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
-// List-based Chooser - typesafe (Page 129)
+// 코드 28-6 리스트 기반 Chooser - 타입 안전성 확보! (168쪽)
public class Chooser {
private final List choiceList;
diff --git a/src/effectivejava/chapter5/item29/technqiue1/Stack.java b/src/effectivejava/chapter5/item29/technqiue1/Stack.java
index fbaa60b7..308e696b 100644
--- a/src/effectivejava/chapter5/item29/technqiue1/Stack.java
+++ b/src/effectivejava/chapter5/item29/technqiue1/Stack.java
@@ -3,15 +3,16 @@
import java.util.Arrays;
-// Generic stack using E[] (Pages 130-3)
+// E[]를 이용한 제네릭 스택 (170-174쪽)
public class Stack {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
- // The elements array will contain only E instances from push(E).
- // This is sufficient to ensure type safety, but the runtime
- // type of the array won't be E[]; it will always be Object[]!
+ // 코드 29-3 배열을 사용한 코드를 제네릭으로 만드는 방법 1 (172쪽)
+ // 배열 elements는 push(E)로 넘어온 E 인스턴스만 담는다.
+ // 따라서 타입 안전성을 보장하지만,
+ // 이 배열의 런타임 타입은 E[]가 아닌 Object[]다!
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
@@ -26,7 +27,7 @@ public E pop() {
if (size == 0)
throw new EmptyStackException();
E result = elements[--size];
- elements[size] = null; // Eliminate obsolete reference
+ elements[size] = null; // 다 쓴 참조 해제
return result;
}
@@ -39,7 +40,7 @@ private void ensureCapacity() {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
- // Little program to exercise our generic Stack
+ // 코드 29-5 제네릭 Stack을 사용하는 맛보기 프로그램 (174쪽)
public static void main(String[] args) {
Stack stack = new Stack<>();
for (String arg : args)
diff --git a/src/effectivejava/chapter5/item29/technqiue2/Stack.java b/src/effectivejava/chapter5/item29/technqiue2/Stack.java
index bf1632d3..8c894f17 100644
--- a/src/effectivejava/chapter5/item29/technqiue2/Stack.java
+++ b/src/effectivejava/chapter5/item29/technqiue2/Stack.java
@@ -3,7 +3,7 @@
import java.util.Arrays;
import effectivejava.chapter5.item29.EmptyStackException;
-// Generic stack using Object[] (Pages 130-3)
+// Object[]를 이용한 제네릭 Stack (170-174쪽)
public class Stack {
private Object[] elements;
private int size = 0;
@@ -18,16 +18,17 @@ public void push(E e) {
elements[size++] = e;
}
- // Appropriate suppression of unchecked warning
+ // 코드 29-4 배열을 사용한 코드를 제네릭으로 만드는 방법 2 (173쪽)
+ // 비검사 경고를 적절히 숨긴다.
public E pop() {
if (size == 0)
throw new EmptyStackException();
- // push requires elements to be of type E, so cast is correct
+ // push에서 E 타입만 허용하므로 이 형변환은 안전하다.
@SuppressWarnings("unchecked") E result =
(E) elements[--size];
- elements[size] = null; // Eliminate obsolete reference
+ elements[size] = null; // 다 쓴 참조 해제
return result;
}
@@ -40,7 +41,7 @@ private void ensureCapacity() {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
- // Little program to exercise our generic Stack
+ // 코드 29-5 제네릭 Stack을 사용하는 맛보기 프로그램 (174쪽)
public static void main(String[] args) {
Stack stack = new Stack<>();
for (String arg : args)
diff --git a/src/effectivejava/chapter5/item30/GenericSingletonFactory.java b/src/effectivejava/chapter5/item30/GenericSingletonFactory.java
index 6f27af8b..51061c54 100644
--- a/src/effectivejava/chapter5/item30/GenericSingletonFactory.java
+++ b/src/effectivejava/chapter5/item30/GenericSingletonFactory.java
@@ -2,9 +2,9 @@
import java.util.function.UnaryOperator;
-// Generic singleton factory pattern (Page 136-7)
+// 제네릭 싱글턴 팩터리 패턴 (178쪽)
public class GenericSingletonFactory {
- // Generic singleton factory pattern
+ // 코드 30-4 제네릭 싱글턴 팩터리 패턴 (178쪽)
private static UnaryOperator IDENTITY_FN = (t) -> t;
@SuppressWarnings("unchecked")
@@ -12,9 +12,9 @@ public static UnaryOperator identityFunction() {
return (UnaryOperator) IDENTITY_FN;
}
- // Sample program to exercise generic singleton
+ // 코드 30-5 제네릭 싱글턴을 사용하는 예 (178쪽)
public static void main(String[] args) {
- String[] strings = { "jute", "hemp", "nylon" };
+ String[] strings = { "삼베", "대마", "나일론" };
UnaryOperator sameString = identityFunction();
for (String s : strings)
System.out.println(sameString.apply(s));
@@ -24,4 +24,4 @@ public static void main(String[] args) {
for (Number n : numbers)
System.out.println(sameNumber.apply(n));
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter5/item30/RecursiveTypeBound.java b/src/effectivejava/chapter5/item30/RecursiveTypeBound.java
index e3419dfc..2a597c4a 100644
--- a/src/effectivejava/chapter5/item30/RecursiveTypeBound.java
+++ b/src/effectivejava/chapter5/item30/RecursiveTypeBound.java
@@ -1,12 +1,12 @@
package effectivejava.chapter5.item30;
import java.util.*;
-// Using a recursive type bound to express mutual comparability (Pages 137-8)
+// 재귀적 타입 한정을 이용해 상호 비교할 수 있음을 표현 (179쪽)
public class RecursiveTypeBound {
- // Returns max value in a collection - uses recursive type bound
+ // 코드 30-7 컬렉션에서 최댓값을 반환한다. - 재귀적 타입 한정 사용 (179쪽)
public static > E max(Collection c) {
if (c.isEmpty())
- throw new IllegalArgumentException("Empty collection");
+ throw new IllegalArgumentException("컬렉션이 비어 있습니다.");
E result = null;
for (E e : c)
@@ -20,4 +20,4 @@ public static void main(String[] args) {
List argList = Arrays.asList(args);
System.out.println(max(argList));
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter5/item30/Union.java b/src/effectivejava/chapter5/item30/Union.java
index 5ecb202f..9f47b935 100644
--- a/src/effectivejava/chapter5/item30/Union.java
+++ b/src/effectivejava/chapter5/item30/Union.java
@@ -1,20 +1,20 @@
package effectivejava.chapter5.item30;
import java.util.*;
-// Generic union method and program to exercise it (Pages 135-6)
+// 제네릭 union 메서드와 테스트 프로그램 (177쪽)
public class Union {
- // Generic method
+ // 코드 30-2 제네릭 메서드 (177쪽)
public static Set union(Set s1, Set s2) {
Set result = new HashSet<>(s1);
result.addAll(s2);
return result;
}
- // Simple program to exercise generic method
+ // 코드 30-3 제네릭 메서드를 활용하는 간단한 프로그램 (177쪽)
public static void main(String[] args) {
- Set guys = Set.of("Tom", "Dick", "Harry");
- Set stooges = Set.of("Larry", "Moe", "Curly");
+ Set guys = Set.of("톰", "딕", "해리");
+ Set stooges = Set.of("래리", "모에", "컬리");
Set aflCio = union(guys, stooges);
System.out.println(aflCio);
}
diff --git a/src/effectivejava/chapter5/item31/Chooser.java b/src/effectivejava/chapter5/item31/Chooser.java
index bb8443d0..de8583a0 100644
--- a/src/effectivejava/chapter5/item31/Chooser.java
+++ b/src/effectivejava/chapter5/item31/Chooser.java
@@ -5,11 +5,12 @@
import java.util.List;
import java.util.Random;
-// Wildcard type for parameter that serves as an T producer (page 141)
+// T 생산자 매개변수에 와일드카드 타입 적용 (184쪽)
public class Chooser {
private final List choiceList;
private final Random rnd = new Random();
+ // 코드 31-5 T 생산자 매개변수에 와일드카드 타입 적용 (184쪽)
public Chooser(Collection extends T> choices) {
choiceList = new ArrayList<>(choices);
}
diff --git a/src/effectivejava/chapter5/item31/RecursiveTypeBound.java b/src/effectivejava/chapter5/item31/RecursiveTypeBound.java
index d50aa1cf..99d779ac 100644
--- a/src/effectivejava/chapter5/item31/RecursiveTypeBound.java
+++ b/src/effectivejava/chapter5/item31/RecursiveTypeBound.java
@@ -1,12 +1,12 @@
package effectivejava.chapter5.item31;
import java.util.*;
-// Using a recursive type bound with wildcards (Page 143)
+// 와일드카드 타입을 사용해 재귀적 타입 한정을 다듬었다. (187쪽)
public class RecursiveTypeBound {
public static > E max(
List extends E> list) {
if (list.isEmpty())
- throw new IllegalArgumentException("Empty list");
+ throw new IllegalArgumentException("빈 리스트");
E result = null;
for (E e : list)
@@ -20,4 +20,4 @@ public static void main(String[] args) {
List argList = Arrays.asList(args);
System.out.println(max(argList));
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter5/item31/Stack.java b/src/effectivejava/chapter5/item31/Stack.java
index a5abe59d..4489e048 100644
--- a/src/effectivejava/chapter5/item31/Stack.java
+++ b/src/effectivejava/chapter5/item31/Stack.java
@@ -1,15 +1,16 @@
package effectivejava.chapter5.item31;
import java.util.*;
-// Generic stack with bulk methods using wildcard types (Pages 139-41)
+// 와일드카드 타입을 이용해 대량 작업을 수행하는 메서드를 포함한 제네릭 스택 (181-183쪽)
public class Stack {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
- // The elements array will contain only E instances from push(E).
- // This is sufficient to ensure type safety, but the runtime
- // type of the array won't be E[]; it will always be Object[]!
+ // 코드 29-3 배열을 사용한 코드를 제네릭으로 만드는 방법 1 (172쪽)
+ // 배열 elements는 push(E)로 넘어온 E 인스턴스만 담는다.
+ // 따라서 타입 안전성을 보장하지만,
+ // 이 배열의 런타임 타입은 E[]가 아닌 Object[]다!
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
@@ -24,7 +25,7 @@ public E pop() {
if (size==0)
throw new EmptyStackException();
E result = elements[--size];
- elements[size] = null; // Eliminate obsolete reference
+ elements[size] = null; // 다 쓴 참조 해제
return result;
}
@@ -37,31 +38,31 @@ private void ensureCapacity() {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
-// // pushAll staticfactory without wildcard type - deficient!
+// // 코드 31-1 와일드카드 타입을 사용하지 않은 pushAll 메서드 - 결함이 있다! (181쪽)
// public void pushAll(Iterable src) {
// for (E e : src)
// push(e);
// }
- // Wildcard type for parameter that serves as an E producer
+ // 코드 31-2 E 생산자(producer) 매개변수에 와일드카드 타입 적용 (182쪽)
public void pushAll(Iterable extends E> src) {
for (E e : src)
push(e);
}
-// // popAll staticfactory without wildcard type - deficient!
+// // 코드 31-3 와일드카드 타입을 사용하지 않은 popAll 메서드 - 결함이 있다! (183쪽)
// public void popAll(Collection dst) {
// while (!isEmpty())
// dst.add(pop());
// }
- // Wildcard type for parameter that serves as an E consumer
+ // 코드 31-4 E 소비자(consumer) 매개변수에 와일드카드 타입 적용 (183쪽)
public void popAll(Collection super E> dst) {
while (!isEmpty())
dst.add(pop());
}
- // Little program to exercise our generic Stack
+ // 제네릭 Stack을 사용하는 맛보기 프로그램
public static void main(String[] args) {
Stack numberStack = new Stack<>();
Iterable integers = Arrays.asList(3, 1, 4, 1, 5, 9);
diff --git a/src/effectivejava/chapter5/item31/Swap.java b/src/effectivejava/chapter5/item31/Swap.java
index 776f886f..3fb94038 100644
--- a/src/effectivejava/chapter5/item31/Swap.java
+++ b/src/effectivejava/chapter5/item31/Swap.java
@@ -1,19 +1,19 @@
package effectivejava.chapter5.item31;
import java.util.*;
-// Private helper method for wildcard capture (Page 145)
+// 와일드카드 타입을 실제 타입으로 바꿔주는 private 도우미 메서드 (189쪽)
public class Swap {
public static void swap(List> list, int i, int j) {
swapHelper(list, i, j);
}
- // Private helper method for wildcard capture
+ // 와일드카드 타입을 실제 타입으로 바꿔주는 private 도우미 메서드
private static void swapHelper(List list, int i, int j) {
list.set(i, list.set(j, list.get(i)));
}
public static void main(String[] args) {
- // Swap the first and last argument and print the resulting list
+ // 첫 번째와 마지막 인수를 스왑한 후 결과 리스트를 출력한다.
List argList = Arrays.asList(args);
swap(argList, 0, argList.size() - 1);
System.out.println(argList);
diff --git a/src/effectivejava/chapter5/item31/Union.java b/src/effectivejava/chapter5/item31/Union.java
index 71cc58b8..92f91e26 100644
--- a/src/effectivejava/chapter5/item31/Union.java
+++ b/src/effectivejava/chapter5/item31/Union.java
@@ -1,7 +1,7 @@
package effectivejava.chapter5.item31;
import java.util.*;
-// Generic union method with wildcard types for enhanced flexibility (Pages 142-3)
+// 코드 30-2의 제네릭 union 메서드에 와일드카드 타입을 적용해 유연성을 높였다. (185-186쪽)
public class Union {
public static Set union(Set extends E> s1,
Set extends E> s2) {
@@ -10,7 +10,7 @@ public static Set union(Set extends E> s1,
return result;
}
- // Simple program to exercise flexible generic staticfactory
+ // 향상된 유연성을 확인해주는 맛보기 프로그램 (185쪽)
public static void main(String[] args) {
Set integers = new HashSet<>();
integers.add(1);
@@ -24,7 +24,7 @@ public static void main(String[] args) {
Set numbers = union(integers, doubles);
-// // Explicit type parameter - required prior to Java 8
+// // 코드 31-6 자바 7까지는 명시적 타입 인수를 사용해야 한다. (186쪽)
// Set numbers = Union.union(integers, doubles);
System.out.println(numbers);
diff --git a/src/effectivejava/chapter5/item32/Dangerous.java b/src/effectivejava/chapter5/item32/Dangerous.java
index fdd1a499..c61e995a 100644
--- a/src/effectivejava/chapter5/item32/Dangerous.java
+++ b/src/effectivejava/chapter5/item32/Dangerous.java
@@ -2,13 +2,13 @@
import java.util.List;
-// It is unsafe to store a value in a generic varargs array parameter (Page 146)
+// 제네릭 varargs 배열 매개변수에 값을 저장하는 것은 안전하지 않다. (191-192쪽)
public class Dangerous {
- // Mixing generics and varargs can violate type safety!
+ // 코드 32-1 제네릭과 varargs를 혼용하면 타입 안전성이 깨진다! (191-192쪽)
static void dangerous(List... stringLists) {
List intList = List.of(42);
Object[] objects = stringLists;
- objects[0] = intList; // Heap pollution
+ objects[0] = intList; // 힙 오염 발생
String s = stringLists[0].get(0); // ClassCastException
}
diff --git a/src/effectivejava/chapter5/item32/FlattenWithList.java b/src/effectivejava/chapter5/item32/FlattenWithList.java
index b9cbaa71..effabe71 100644
--- a/src/effectivejava/chapter5/item32/FlattenWithList.java
+++ b/src/effectivejava/chapter5/item32/FlattenWithList.java
@@ -3,7 +3,7 @@
import java.util.ArrayList;
import java.util.List;
-// List as a typesafe alternative to a generic varargs parameter (page 149)
+// 코드 32-4 제네릭 varargs 매개변수를 List로 대체한 예 - 타입 안전하다. (195-196쪽)
public class FlattenWithList {
static List flatten(List> lists) {
List result = new ArrayList<>();
diff --git a/src/effectivejava/chapter5/item32/FlattenWithVarargs.java b/src/effectivejava/chapter5/item32/FlattenWithVarargs.java
index e33f4472..5e3e47f6 100644
--- a/src/effectivejava/chapter5/item32/FlattenWithVarargs.java
+++ b/src/effectivejava/chapter5/item32/FlattenWithVarargs.java
@@ -3,7 +3,7 @@
import java.util.ArrayList;
import java.util.List;
-// Safe method with a generic varargs parameter (page 149)
+// 코드 32-3 제네릭 varargs 매개변수를 안전하게 사용하는 메서드 (195쪽)
public class FlattenWithVarargs {
@SafeVarargs
static List flatten(List extends T>... lists) {
diff --git a/src/effectivejava/chapter5/item32/PickTwo.java b/src/effectivejava/chapter5/item32/PickTwo.java
index 297bea62..faa9fce7 100644
--- a/src/effectivejava/chapter5/item32/PickTwo.java
+++ b/src/effectivejava/chapter5/item32/PickTwo.java
@@ -3,9 +3,9 @@
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
-// Subtle heap pollution (Pages 147-8)
+// 미묘한 힙 오염 발생 (193-194쪽)
public class PickTwo {
- // UNSAFE - Exposes a reference to its generic parameter array!
+ // 코드 32-2 자신의 제네릭 매개변수 배열의 참조를 노출한다. - 안전하지 않다! (193쪽)
static T[] toArray(T... args) {
return args;
}
@@ -16,11 +16,11 @@ static T[] pickTwo(T a, T b, T c) {
case 1: return toArray(a, c);
case 2: return toArray(b, c);
}
- throw new AssertionError(); // Can't get here
+ throw new AssertionError(); // 도달할 수 없다.
}
- public static void main(String[] args) {
- String[] attributes = pickTwo("Good", "Fast", "Cheap");
+ public static void main(String[] args) { // (194쪽)
+ String[] attributes = pickTwo("좋은", "빠른", "저렴한");
System.out.println(Arrays.toString(attributes));
}
}
diff --git a/src/effectivejava/chapter5/item32/SafePickTwo.java b/src/effectivejava/chapter5/item32/SafePickTwo.java
index b8d864bf..05de0b0b 100644
--- a/src/effectivejava/chapter5/item32/SafePickTwo.java
+++ b/src/effectivejava/chapter5/item32/SafePickTwo.java
@@ -4,7 +4,7 @@
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
-// Safe version of PickTwo using lists instead of arrays (Page 150)
+// 배열 대신 List를 이용해 안전하게 바꿘 PickTwo (196쪽)
public class SafePickTwo {
static List pickTwo(T a, T b, T c) {
switch(ThreadLocalRandom.current().nextInt(3)) {
@@ -16,7 +16,7 @@ static List pickTwo(T a, T b, T c) {
}
public static void main(String[] args) {
- List attributes = pickTwo("Good", "Fast", "Cheap");
+ List attributes = pickTwo("좋은", "빠른", "저렴한");
System.out.println(attributes);
}
}
diff --git a/src/effectivejava/chapter5/item33/Favorites.java b/src/effectivejava/chapter5/item33/Favorites.java
index 4e3385f7..43a054dc 100644
--- a/src/effectivejava/chapter5/item33/Favorites.java
+++ b/src/effectivejava/chapter5/item33/Favorites.java
@@ -1,8 +1,9 @@
package effectivejava.chapter5.item33;
import java.util.*;
-// Typesafe heterogeneous container pattern (Pages 151-4)
+// 타입 안전 이종 컨테이너 패턴 (199-202쪽)
public class Favorites {
+ // 코드 33-3 타입 안전 이종 컨테이너 패턴 - 구현 (200쪽)
private Map, Object> favorites = new HashMap<>();
public void putFavorite(Class type, T instance) {
@@ -13,20 +14,24 @@ public T getFavorite(Class type) {
return type.cast(favorites.get(type));
}
-// // Achieving runtime type safety with a dynamic cast
+// // 코드 33-4 동적 형변환으로 런타임 타입 안전성 확보 (202쪽)
// public void putFavorite(Class type, T instance) {
// favorites.put(Objects.requireNonNull(type), type.cast(instance));
// }
+ // 코드 33-2 타입 안전 이종 컨테이너 패턴 - 클라이언트 (199쪽)
public static void main(String[] args) {
Favorites f = new Favorites();
+
f.putFavorite(String.class, "Java");
f.putFavorite(Integer.class, 0xcafebabe);
f.putFavorite(Class.class, Favorites.class);
+
String favoriteString = f.getFavorite(String.class);
int favoriteInteger = f.getFavorite(Integer.class);
Class> favoriteClass = f.getFavorite(Class.class);
+
System.out.printf("%s %x %s%n", favoriteString,
favoriteInteger, favoriteClass.getName());
}
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter5/item33/PrintAnnotation.java b/src/effectivejava/chapter5/item33/PrintAnnotation.java
index bbd3d13c..c0eb3fb7 100644
--- a/src/effectivejava/chapter5/item33/PrintAnnotation.java
+++ b/src/effectivejava/chapter5/item33/PrintAnnotation.java
@@ -2,11 +2,11 @@
import java.lang.annotation.*;
import java.lang.reflect.*;
-// Use of asSubclass to safely cast to a bounded type token (Page 155)
+// 코드 33-5 asSubclass를 사용해 한정적 타입 토큰을 안전하게 형변환한다. (204쪽)
public class PrintAnnotation {
static Annotation getAnnotation(AnnotatedElement element,
String annotationTypeName) {
- Class> annotationType = null; // Unbounded type token
+ Class> annotationType = null; // 비한정적 타입 토큰
try {
annotationType = Class.forName(annotationTypeName);
} catch (Exception ex) {
@@ -16,11 +16,11 @@ static Annotation getAnnotation(AnnotatedElement element,
annotationType.asSubclass(Annotation.class));
}
- // Test program to print named annotation of named class
+ // 명시한 클래스의 명시한 애너테이션을 출력하는 테스트 프로그램
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.out.println(
- "Usage: java PrintAnnotation ");
+ "사용법: java PrintAnnotation ");
System.exit(1);
}
String className = args[0];
diff --git a/src/effectivejava/chapter6/item34/Inverse.java b/src/effectivejava/chapter6/item34/Inverse.java
index cced1080..ae0bd2f2 100644
--- a/src/effectivejava/chapter6/item34/Inverse.java
+++ b/src/effectivejava/chapter6/item34/Inverse.java
@@ -1,6 +1,6 @@
package effectivejava.chapter6.item34;
-// Switch on an enum to simulate a missing method (Page 167)
+// 코드 34-10 switch 문을 이용해 원래 열거 타입에 없는 기능을 수행한다. (219쪽)
public class Inverse {
public static Operation inverse(Operation op) {
switch(op) {
diff --git a/src/effectivejava/chapter6/item34/Operation.java b/src/effectivejava/chapter6/item34/Operation.java
index ba89c8f9..a54b10cd 100644
--- a/src/effectivejava/chapter6/item34/Operation.java
+++ b/src/effectivejava/chapter6/item34/Operation.java
@@ -4,7 +4,7 @@
import static java.util.stream.Collectors.toMap;
-// Enum type with constant-specific class bodies and data (Pages 163-4)
+// 코드 34-6 상수별 클래스 몸체(class body)와 데이터를 사용한 열거 타입 (215-216쪽)
public enum Operation {
PLUS("+") {
public double apply(double x, double y) { return x + y; }
@@ -27,12 +27,12 @@ public enum Operation {
public abstract double apply(double x, double y);
- // Implementing a fromString method on an enum type (Page 164)
+ // 코드 34-7 열거 타입용 fromString 메서드 구현하기 (216쪽)
private static final Map stringToEnum =
Stream.of(values()).collect(
toMap(Object::toString, e -> e));
- // Returns Operation for string, if any
+ // 지정한 문자열에 해당하는 Operation을 (존재한다면) 반환한다.
public static Optional fromString(String symbol) {
return Optional.ofNullable(stringToEnum.get(symbol));
}
diff --git a/src/effectivejava/chapter6/item34/PayrollDay.java b/src/effectivejava/chapter6/item34/PayrollDay.java
index 54a89c12..25ccf54c 100644
--- a/src/effectivejava/chapter6/item34/PayrollDay.java
+++ b/src/effectivejava/chapter6/item34/PayrollDay.java
@@ -2,21 +2,30 @@
import static effectivejava.chapter6.item34.PayrollDay.PayType.*;
-// The strategy enum pattern (Page 166)
+// 코드 34-9 전략 열거 타입 패턴 (218-219쪽)
enum PayrollDay {
MONDAY(WEEKDAY), TUESDAY(WEEKDAY), WEDNESDAY(WEEKDAY),
THURSDAY(WEEKDAY), FRIDAY(WEEKDAY),
SATURDAY(WEEKEND), SUNDAY(WEEKEND);
+ // (역자 노트) 원서 1~3쇄와 한국어판 1쇄에는 위의 3줄이 아래처럼 인쇄돼 있습니다.
+ //
+ // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
+ // SATURDAY(PayType.WEEKEND), SUNDAY(PayType.WEEKEND);
+ //
+ // 저자가 코드를 간결하게 하기 위해 매개변수 없는 기본 생성자를 추가했기 때문인데,
+ // 열거 타입에 새로운 값을 추가할 때마다 적절한 전략 열거 타입을 선택하도록 프로그래머에게 강제하겠다는
+ // 이 패턴의 의도를 잘못 전달할 수 있어서 원서 4쇄부터 코드를 수정할 계획입니다.
private final PayType payType;
PayrollDay(PayType payType) { this.payType = payType; }
-
+ // PayrollDay() { this(PayType.WEEKDAY); } // (역자 노트) 원서 4쇄부터 삭제
+
int pay(int minutesWorked, int payRate) {
return payType.pay(minutesWorked, payRate);
}
- // The strategy enum type
+ // 전략 열거 타입
enum PayType {
WEEKDAY {
int overtimePay(int minsWorked, int payRate) {
diff --git a/src/effectivejava/chapter6/item34/Planet.java b/src/effectivejava/chapter6/item34/Planet.java
index af74c405..f6735259 100644
--- a/src/effectivejava/chapter6/item34/Planet.java
+++ b/src/effectivejava/chapter6/item34/Planet.java
@@ -1,6 +1,6 @@
package effectivejava.chapter6.item34;
-// Enum type with data and behavior (159-160)
+// 코드 34-3 데이터와 메서드를 갖는 열거 타입 (211쪽)
public enum Planet {
MERCURY(3.302e+23, 2.439e6),
VENUS (4.869e+24, 6.052e6),
@@ -11,14 +11,14 @@ public enum Planet {
URANUS (8.683e+25, 2.556e7),
NEPTUNE(1.024e+26, 2.477e7);
- private final double mass; // In kilograms
- private final double radius; // In meters
- private final double surfaceGravity; // In m / s^2
+ private final double mass; // 질량(단위: 킬로그램)
+ private final double radius; // 반지름(단위: 미터)
+ private final double surfaceGravity; // 표면중력(단위: m / s^2)
- // Universal gravitational constant in m^3 / kg s^2
+ // 중력상수(단위: m^3 / kg s^2)
private static final double G = 6.67300E-11;
- // Constructor
+ // 생성자
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
diff --git a/src/effectivejava/chapter6/item34/WeightTable.java b/src/effectivejava/chapter6/item34/WeightTable.java
index 948c2e37..15036314 100644
--- a/src/effectivejava/chapter6/item34/WeightTable.java
+++ b/src/effectivejava/chapter6/item34/WeightTable.java
@@ -1,12 +1,12 @@
package effectivejava.chapter6.item34;
-// Takes earth-weight and prints table of weights on all planets (Page 160)
+// 어떤 객체의 지구에서의 무게를 입력받아 여덟 행성에서의 무게를 출력한다. (212쪽)
public class WeightTable {
public static void main(String[] args) {
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight / Planet.EARTH.surfaceGravity();
for (Planet p : Planet.values())
- System.out.printf("Weight on %s is %f%n",
- p, p.surfaceWeight(mass));
+ System.out.printf("%s에서의 무게는 %f이다.%n",
+ p, p.surfaceWeight(mass));
}
}
diff --git a/src/effectivejava/chapter6/item35/Ensemble.java b/src/effectivejava/chapter6/item35/Ensemble.java
index 51e21a32..8c4cd407 100644
--- a/src/effectivejava/chapter6/item35/Ensemble.java
+++ b/src/effectivejava/chapter6/item35/Ensemble.java
@@ -1,6 +1,6 @@
package effectivejava.chapter6.item35;
-// Enum with integer data stored in an instance field (Page 168)
+// 인스턴스 필드에 정수 데이터를 저장하는 열거 타입 (222쪽)
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),
@@ -9,4 +9,4 @@ public enum Ensemble {
private final int numberOfMusicians;
Ensemble(int size) { this.numberOfMusicians = size; }
public int numberOfMusicians() { return numberOfMusicians; }
-}
\ No newline at end of file
+}
diff --git a/src/effectivejava/chapter6/item36/Text.java b/src/effectivejava/chapter6/item36/Text.java
index 9f8aa6cd..3bc5cd44 100644
--- a/src/effectivejava/chapter6/item36/Text.java
+++ b/src/effectivejava/chapter6/item36/Text.java
@@ -2,19 +2,19 @@
import java.util.*;
-// EnumSet - a modern replacement for bit fields (Page 170)
+// 코드 36-2 EnumSet - 비트 필드를 대체하는 현대적 기법 (224쪽)
public class Text {
public enum Style {BOLD, ITALIC, UNDERLINE, STRIKETHROUGH}
- // Any Set could be passed in, but EnumSet is clearly best
+ // 어떤 Set을 넘겨도 되나, EnumSet이 가장 좋다.
public void applyStyles(Set