목록전체 글 (115)
도당탕탕
평범한 concrete 클래스(인스턴스를 만들 수 있는 완전한 클래스)를 상속하는 것은 위험하다. 슈퍼 클래스의 구현이 계속 바뀔 수 있고, 바뀌는 경우 서브 클래스가 더 이상 동작하지 않을 수 있다. 단 슈퍼클래스의 작성자가 상속을 목적으로 정의한 경우라면 상속해도 좋다. 부적절한 상속의 예는 아래와 같다. public class InstrumentedHashSet extends HashSet { private int addCount = 0; public InstrumentedHashSet(){} public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap,loadFactor); } @Override public boolean ad..
불변 클래스란 인스턴스의 내부 값을 수정할 수 없는 클래스를 말한다. 불변 클래스가 가지고 있는 정보는 고정되어 객체가 없어지는 순간까지 절대 달라지지 않는다. 자바 라이브러리에서 가장 대표적인 불변 클래스가 String, primitve 타입의 박싱 된 클래스, BigIntegner, BigDecimal 등이 있다. 불변 클래스는 다음과 같은 장점이 있다. 바로 구현하고 사용하기 쉬우며, 오류가 생길 여지가 적어 훨씬 안전하다. 그럼 어떻게 불변을 만들지 알아보자. 불변 클래스의 다섯가지 규칙 클래스를 불변으로 만들려면 다음과 같이 5가지의 규칙을 따라야 한다. 객체의 상태를 변경하는 메서드를 제공하지 않는다. 클래스를 확장할 수 없도록 한다. ( 나쁜 의도로 객체의 상태를 변하게 만드는 사태를 막아주..
다음과 같은 클래스가 있다고 가정하자. 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..