본문 바로가기

STUDY/이펙티브자바

(44)
아이템 83: 지연 초기화는 신중히 사용하라 지연 초기화 public class FileUtil { private File oldfile = new File("oldfile"); ... } 여기 FileUtil 클래스가 있다. 이 클래스의 oldfile 필드가 프로그램이 100번 실행될 때 한 번 사용될 까 말까하는 필드라면 어떨까? 100번 실행되는 동안 사용하지도 않을 oldfile을 계속 불러와서 초기화 할 것이고 이는 명백한 리소스 낭비이다. 지연 초기화는 위와 같은 문제에 대한 해답이 될 수 있다. 자주 사용되지 않는 필드를 프로그램이 시작할 때가 아니라 비로소 사용될 때 초기화 하는 것이다. public class OldFileUtil { private File oldfile = null; ... public File getOldFile..
아이템 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(..
9-9) 리플렉션보다는 인터페이스를 사용하라 자바 리플렉션 // effectivejava 패키지에 선언된 Person 클래스 package effectivejava; public class Person { private int age; private String name; public Person(int age, String name) { super(); this.age = age; this.name = name; } @Override public String toString() { return "Person [age=" + age + ", name=" + name + "]"; } } // 다른 .java 파일의 main 코드 Class personClass = Class.forName("effectivejava.Person"); for(Field..
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) { ... } 메소드 시그니처란 메소드의 고유성을 나타내는 요소들을 말한다. 메소드 시그니쳐가 동일한 메소드는 중복된 메소드를 만드는 것이기 때문에 컴파일 에러가 발생한다. 언어마다 다르지만 자바에서는 메소드 명과 파..