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 -![EJ3e Book Cover](https://www.pearsonhighered.com/assets/bigcovers/0/1/3/4/0134685997.jpg) -## 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 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 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 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 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 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 s1, Set s2) { @@ -10,7 +10,7 @@ public static Set union(Set 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... 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