목록이펙티브자바 (88)
도당탕탕
다음과 같은 클래스가 있다고 가정하자. public class Point { public double x; public double y; } 위 클래스는 캡슐화의 이점을 누리지 못한다. API의 변경 없이 표현방식을 바꿀 수도 없고(예를 들어, 위의 변수를 지우고 다른 변수를 정의하면 표현방식이 변경되는 동시에 API 또한 변경이 되어 버린다.), 특정 규칙을 강요할 수도 없으며(예를 들어, 범위를 강제하는 것) 필드에 접근될 때 추가적인 작업을 수행할 수도 없다. 따라서 다음과 같이 정의하여, 클래스의 내부표현 방식을 변경할 수 있도록 해야 한다. public class Point { private double x; private double y; public Point(double x, double ..
어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐이다. 잘 설계된 컴포넌트는 모든 내부 구현을 완벽히 숨겨, 구현과 API를 깔끔히 분리한다. 오직 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작 방식에는 전혀 개의치 않는다. 이러한 개념을 정보 은닉이라 표한다. 정보 은닉 정보 은닉은 장점이 많은데 살펴보면 다음과 같다. 시스템 개발 속도를 높인다. - 여러 컴포넌트를 병렬로 개발할 수 있기 때문이다. 시스템 관리 비용을 낮춘다. - 각 컴포넌트를 더 빨리 파악하여 디버깅할 수 있고, 다른 컴포넌트로 교체하는 부담이 적기 때문이다. 정보 은닉 자체가 성능을 높혀주지 않지만 성능 최적화에 도움을 준다..
public class WordList { public static void main(String[] args) { Set s = new TreeSet(); Collections.addAll(s,args); System.out.println(s); } } String 은 Comparable 을 구현하고 있기 때문에, 위와 같이 TreeSet 에 추가하면 알파벳순서대로 String이 정렬되고 중복이 제거된다.Comparable 을 구현함으로써, 많은 generic 알고리즘과 컬렉션 구현과 호환되도록 할수 있다. 일반적인 규칙 * sgn 함수는 -1,0,1 을 반환하는 함수. * sgn(x) == -1 if x 0 대칭성..
Item13 : clone 재정의는 주의해서 진행하라 Clonable은 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스이다. 하지만 의도한 목적을 제대로 이루지 못했고 가장 큰 문제는 clone 메소드가 선언된 곳이 Cloneable이 아닌 Object이고, 그마저 protected라는데에 있다. 그래서 Cloneable을 구현하는 것만으로는 외부 객체에서 clone 메소드를 호출할 수 없다. Object 클래스와 Cloneable 인터페이스에서 clone 메소드와의 관계 public class Object { ... @HotSpotIntrinsicCandidate // clone 메소드가 Object에 선언, protected로 선언 protected native Object clone() ..
PhoneNumber 라는 클래스가 있을때, toString 함수를 정의하지 않으면, {PhoneNumber@163b91} 라는 값을 리턴한다. 하지만 이 보다는 {707-867-5309} 와 같은 형식이 더 유용한 정보를 제공한다. toString 함수는 가급적 객체가 담고있는 모든 정보를 리턴하는 것이 좋다. 하지만 String으로 변환하기 적절하지 않은 경우도 있다. 보통 그럴 경우 toString 함수는 최대한 요약한 정보를 리턴해야한다. (Thread[main,5 main].) toString 함수를 구현할때, 결정해야하는 것중 하나는 포맷을 명시할지 말지이다. 만약 포맷을 명시한다면, 표준적이고 가독성이 좋은 문자열을 리턴한다는 장점이 있다. 많은 value class(BigInteger,Bi..
equals를 재정의한 클래스 모두에서 hashCode도 재정의 해야한다. 만약 재정의를 하지 않으면 hashCode의 일반 규약을 어겨 해당 클래스의 인스턴스를 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다. 여기서 Object의 명세 규약을 보자! Object의 HashCode 명세 규약 equals 비교에 사용되는 정보가 변경되지 않았다면, 어플리케이션이 실행되는 동안 객체에서 hashCode 메소드는 몇번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. 단 어플리케이션을 다시 실행한다면 이 값이 달라져도 상관없다. Equals(Object) 가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다. Equals(Object..
1. 일반적인 규칙 Reflexive : null이 아닌 레퍼런스 value x에 대해서, x.equals(x) == true 여야한다. Symmetric : null이 아닌 레퍼런스 value x,y에 대해서, x.equals(y) == true 이면 y.equals(x) == true여야 한다. Transitive : null이 아닌 레퍼런스 value x,y,z에 대해서, x.equals(y) == true, y.equals(z) == true이면 x.equals(z) == true Consistent : null이 아닌 레퍼런스 value x,y에 대해서, x.equals(y)는 여러번 호출해도 같은 값을 리턴해야한다. (내부 값이 변경되지 않았다는 가정하에) null이 아닌 value x에 대해..
자바에서는 resource를 사용하고 close를 사용해 닫아야 하는 메소드들이 많다. 대표적인 예로 InputStream, OutputStream, dbConnection을 들수 있다. 만약 이 자원들을 닫지 않으면 시스템은 성능 문제를 야기 시킬 수 있다. 그렇기 때문에 전통적으로 자바에서는 finalizer를 활용해 자원을 닫아주는 것을 보장 했었다. 그렇지만 finalizer는 item8에서 봤듯이 언제 JVM에서 호출을 해줄지 모르기 때문에 별로 믿을만하지 못하다. 또한 다음과 같은 단점도 보인다. 예를 한번 보자. try-finally를 이용해 자원을 회수 하는 코드 static String firstLineOfFile(String path) throws IOException { Buffere..