JAVA/이펙티브 자바
6. 불필요한 객체 생성을 피하라
똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 간단한 예로 String s1 = new String(" aaa " ) ; String s2 = " aaa " ; 위 문장은 실행될 때 마다 String 인스턴스를 새로 만든다. 이 문장을 반복문이나 자주 호출되는 메서드 안에 넣으면 s1을 사용할 때 마다 " aaa " 라는 String 인스턴스가 계속 생성된다. 아래 문장은 하나의 String 인스턴스를 사용한다. 생성자 대신 정적 팩터리 메서드를 제공하는 불변 클래스에서는 싱글턴을 보장해 불필요한 객체 생성을 피할 수 있다. public class RomanNumerals { // 코드 6-1 성능을 훨씬 더 끌어올릴 수 있다! static boolean isRo..
5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
많은 클래스가 하나 이상의 자원에 의존한다. 예를 들어 사전에 의존하는 맞춤법 검사기 어플리케이션이 있다. 정적 유틸리티 public class SpellChecker { private static final Dictionary dictionary = new DefaultDictionary(); private SpellChecker() {} public static boolean isValid(String word) { // TODO 여기 SpellChecker 코드 return dictionary.contains(word); } public static List suggestions(String typo) { // TODO 여기 SpellChecker 코드 return dictionary.closeWo..
4. 인스턴스화를 막으려면 private 생성자를 사용하라
이따금 단순히 정적 메서드와 정적 필드만 담은 클래스를 만들어야할 때가 있다. 정적 멤버만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한게 아니다. 하지만 생성자를 명시하지 않으면 컴파일러가 자동으로 기본 생성자를 만든다. 즉, 매개변수를 받지 않는 public 생성자가 만들어지고, 사용자는 설계자가 생성자를 의도한건지, 아니면 실수로 자동생성된건지 구분 할 수 없다. 실제로 공개된 API에서 의도치않게 인스턴스화 할 수 있게 된 클래스들이 보일 때가 있다. 추상 클래스로 만드는 것으로는 인스턴스화를 막을 수 없다. 하위 클래스를 만들어서 인스턴스화 하면 그만이다. 이것은 사용자에게 상속해서 쓰라는 오해를 불러일으킬 수 있다. 이런 오해를 막기위해 private 생성자를 추가하면 클래스의 인스턴..
3. private 생성자나 열거타입으로 싱글턴을 보증하라
싱글턴이란 인스턴스를 오직 하나만 생성할 수 있는 클래스를 말한다. 클래스를 싱글턴으로 만들면 이를 사용하는 클라이언트를 테스트하기가 어려워질 수 있다. 타입을 인터페이스로 정의한 다음 그 인터페이스를 구현해서 만든 싱글턴이 아니라면 싱글턴 인스턴스를 가짜 구현으로 대체할 수 없다. 싱글턴을 만드는 방식은 보통 둘 중 하나다. 두 방식 모두 생성자는 private로 감춰두고 , 유일한 인스턴스에 접근할 수 있는 수단으로 public 적정 멤버를 만들어둔다. public static final 필드 방식의 싱글턴 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { } public void leaveT..
2. 생성자에 매개변수가 많다면 빌더를 고려하라
정적 팩터리 메서드와 생성자에는 같은 제약이 있다. 매개변수의 변동이 많을 때 적절히 대응하기 어려워 지는 것이다. 프로그래머들은 이럴 때 점층적 생성자 패턴을 즐겨 사용했다. 점층적 생성자 패턴이란 쉽게 말해 여러개의 생성자를 만드는 것이다. 매개변수가 다른 생성자들을 만들어 각각의 상황에 대응하지만 한계가 명확히 보인다. 코드가 복잡해지는 것 뿐만 아니라 매개변수가 추가되거나 변경될 때 마다 생성자를 변경해줘야 한다. 그 다음은 getter/setter를 사용하는 자바 빈즈 패턴이 있다. new로 객체를 생성하고, setter를 이용해 값을 넣어줄 수 있다. 하지만 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓이게 된다. 값이 유효한지 알 수 없고, 값을 어디까지 설정해줘야 하는지 알 수..
1. 생성자 대신 정적 팩터리 메서드를 고려하라
클래스의 인스턴스를 얻는 전통적인 방법은 public 생성자이다. 하지만 클래스는 생성자와 별도로 클래스의 인스턴스를 반환하는 static factory method를 제공 할 수 있다. 이 방식에는 장단점이 모두 존재한다. 장점 1. 이름을 가질 수 있다. 생성자는 매개변수와 생성자만으로는 반환될 객체를 제대로 설명 할 수 없다. 하지만 정적 팩터리 메소드는 네이밍을 통해 반활될 객체의 특성을 설명할 수 있다. 예를들어 생성자인 BingInteger(int , int , Random) 과 정적 팩터리 BingInteger.probablePrime 중, 어느 쪽이 값이 소수인 BigInteger를 반환하는 것에 대하여 잘 설명할 수 있을지를 생각해보자. 프로젝트 중 하나의 인터페이스에서 특정 매개변수를 ..
HashMap이란?
HashMap은 대표적인 Map 컬렉션 중 하나이다. Map 컬렉션에는 HashMap, Hashtable, LinkedHashMap, Properties, TreeMap 등이 있다. Map인터페이스를 상속하고 있기 때문에 Map의 성질을 그대로 가지고 있다. 키와 값은 모두 객체이고, 값은 중복저장될 수 있지만, 키는 중복저장될 수 없다. 키를 중복저장하면 기존의 값은 사라지고 새로 등록한 값이 저장된다. HashMap은 이름 그대로 해싱(Hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는 데 있어서 뛰어난 성능을 보인다고 한다. 키 (key) 값 (value)은 간단하다. HasMap의 사용법은 HashMap map(내가 설정하고 싶은 이름) = new HashMap(); new로 HashM..