본문 바로가기

Effective Java

(40)
아이템 82: 스레드 안정성 수준을 문서화하라 스레드 안정성 문서화 클래스를 개발할 때, 해당 클래스를 사용할 클라이언트들을 위하여 필요한 정보들을 주석으로 작성하여 문서화 해야한다. 아무런 설명이 없다면 클라이언트는 추측과 가정을 통해 그 클래스를 사용하게 된다. 특히 스레드 안정성에 대한 정보는 설명이 필요한 중요한 정보 중 하나이다. 스레드 안정성이 잘못되면 프로그램에 심각한 오류가 발생할 것이다. 스레드 안정성 수준 불변(immutable): 이 클래스의 인스턴스는 마치 상수와 같아서 외부 동기화가 필요없다. 무조건적 스레드 안전(unconditionally thread-safe): 이 클래스의 인스턴스는 수정될 수 있으나, 내부에서 충실히 동기화하여 별도의 외부 동기화 없이 동시에 사용해도 안전하다. 조건부 스레드 안전(conditional..
아이템 81: 동시성 유틸리티를 애용하라 wait와 notify public class Main { public synchronized void waitMehod() throws InterruptedException { System.out.println(Thread.currentThread().getId() + " wait"); wait(); System.out.println(Thread.currentThread().getId() + " notified"); } public synchronized void notifyMethod() throws InterruptedException { System.out.println(Thread.currentThread().getId() + " notify all"); notifyAll(); } public ..
9-11) 최적화는 신중히 하라 빠른 프로그램보다 좋은 프로그램을 작성하라 최적화를 할 때는 다음 두 규칙을 따르라. 첫 번째, 하지마라. 두 번째, (전문가 한정) 아직 하지 마라. 다시 말해, 완전히 명백하고 최적화되지 않은 해법을 찾을 때까지는 하지 마라. - M.A 잭슨 (Jackson75) 위의 격언은 최적화의 어두운 진실을 이야기해준다. 최적화는 섣불리 진행하면 오히려 안좋은 결과를 불러올 수 있다. 성능보다 중요한 것은 견고한 구조를 가진 좋은 프로그램을 작성하는 것이다. 프로그램의 구성요소들이 각각 독립된 책임을 가지고 동작해야 한다. 그러면 나머지 시스템에 영향을 주지 않고 각 요소를 다시 수정할 수 있을 것이다. 그렇다고 성능을 무시하라는 것은 아니다. 다만 지엽적인 구현상의 최적화에 신경쓰기 보다는 설계상의 성능에 ..
9-10) 네이티브 메소드는 신중히 사용하라 자바 네이티브 인터페이스(JNI) 자바 네이티브 인터페이스는 자바 프로그램이 C/C++ 같은 네이티브 언어로 작성된 프로그램을 호출하는 기술이다. JNI는 플랫폼 특화 기술을 활용 하거나, 네이티브 언어로 작성된 기존 라이브러리를 사용하거나, 성능 개선을 하고 싶을때 사용한다. 하지만 자바가 성숙해가면서 플랫폼의 기능들을 점차 흡수하고 있고, 자바로 작성된 라이브러리의 수도 상당히 늘어났다. 또 JVM이 발전하면서 자바의 성능도 상당부분 개선이 되었기 때문에 네이티브 메소드를 사용해야하는 상황은 흔치않다. JNI 실습 // JNI.java public class JNI { static { System.loadLibrary("JNI"); } private native void printHelloWorld(..
8-4) 메소드 오버로딩은 신중히 사용하라 Collection 분류기 public class CollectionClassifier { public static String classify(Set s) { return "Set"; } public static String classify(List lst) { return "List"; } public static String classify(Collection c) { return "Unknown Collection"; } public static void main(String[] args) { Collection[] collections = { new HashSet(), new ArrayList(), new HashMap().values() }; for (Collection c : collecti..
8-3) 메소드 시그니처를 신중히 설계하라 메소드 시그니처 private String myFunc(Integer num) { ... } // 메소드 시그니처가 다르기때문에 컴파일 에러가 발생하지 않는다. public final Integer myFunc(String str) { ... } private String myFunc(Integer num) { ... } // 공개범위, final 키워드, 반환 타입이 다르지만 중복된 메소드로 컴파일 에러가 발생한다. public final Integer myFunc(Integer num) { ... } 메소드 시그니처란 메소드의 고유성을 나타내는 요소들을 말한다. 메소드 시그니쳐가 동일한 메소드는 중복된 메소드를 만드는 것이기 때문에 컴파일 에러가 발생한다. 언어마다 다르지만 자바에서는 메소드 명과 파..
8-2) 방어적 복사본을 만들라 자바는 안전한 언어다 int nums1[4] = {1,2,3,4}; int nums2[4] = {5,6,7,8}; // 5 출력 std::cout 0) throw new IllegalArgumentException( this.start + " after " + this.end); } public Date start() { return new Date(start.getTime()); } public Date end() { return new Date(end.getTime()); } } // 이제 Period에 사용된 Date 객체의 값이 바뀌어도 영향이 없다. Date start = new Date(); Date end = new Date(); Period p = new Period(start, end);..
8-1) 매개변수가 유효한지 검사하라 매개변수 유효성 검사 // NullPointerException 발생 List nums = Collections.synchronizedList(null); ... 메소드나 생성자의 내부 동작은 정상적인 파라미터가 전달될 것이라는 것을 전제로 한다. 예를 인덱스 값은 음수가 아니고 객체는 null이 아니라는 것이다. 하지만 개발중 실수로 잘못된 값이 전달되지 않을거라는 보장은 없기 때문에 매개변수의 유효성 검사는 필요하다. 그리고 오류를 가능한 빨리 (근본적인 오류가 발생한 곳에서) 잡는것에도 도움이 된다. 위의 코드를 보면 Collections.synchronizedList(null); 메소드를 호출한 시점부터 파라미터 유효성 검사에 걸려서 에러가 발생한다. 하지만 만약 저 에러가 발생하지 않았다면, 멀..