
중첩 클래스 (nested class) 중첩 클래스는 다른 클래스 안에 정의된 클래스를 말한다. 자신을 감싼 바깥 클래스에서만 쓰여야함 정적 멤버 클래스, (비정적) 멤버 클래스, 익명 클래스, 지역 클래스 정적 멤버 클래스 다른 클래스 내부에서 static으로 선언된 클래스 다른 정적 멤버와 똑같은 규칙 적용 흔히 바깥 클래스와 함께 쓰일때만 유용한 public 도우미 클래스로 사용 public class Calculator { public enum Operation { // 열거 타입도 암시적 static 이다. PLUS, MINUS, MULTIPLE, SUBTRACT } } 비정적 멤버 클래스 다른 클래스 내부에서 static 없이 선언된 클래스 비정적 멤버 클래스 인스턴스는 바깥 클래스 인스턴스와..

태그 달린 클래스 두 가지 이상의 의미를 표현할 수 있고 현재 표현하는 의미를 태그 값으로 알려주는 클래스 public class Figure { enum Shape {RECTANGLE, CIRCLE} // 태그 private final Shape shape; // 이 필드들은 사각형일때만 사용 private final double length; private final double width; // 이 필드는 원형일때만 사용 private final double radius; //원용 생성자 public Figure(Shape shape, double radius) { this.shape = shape; this.length = 0; this.width = 0; this.radius = radius; ..

인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 하는데, 인터페이스는 이 용도로만 사용해야 한다. 상수 인터페이스는 메서드 없이 static final 필드로만 가득찬 인터페이스로, 인터페이스를 잘못 사용한 예이다. //상수 인터페이스 안티패턴 - 사용금지 public interface PhysicalConstants { static final double AVOGADROS_NUMBER = 6.022_140_857e23; static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23; static final double ELECTRON_MASS = 9.109_383_56e-31; } 클래스 내부의 상수는 외부 인터페이스가 아니라 내부 구..

디폴트 메서드의 도입 - 자바8부터는 기존 인터페이스에 메서드를 추가할 수 있도록 디폴트 메서드를 도입. but 디폴트 메서드를 재정의하지 않은 모든 클래스에서 디폴트 구현이 쓰이게 되므로 모든 기존 구현체들과 매끄럽게 연동되리라는 보장을 할 수 없음 - 자바8에서는 핵심 컬렉션 인터페이스들에 다수의 디폴트 메서드가 추가됨 → 람다 활용 위해 추가된 메서드들은 품질이 높고 범용적이어서 대부분 상황에서 잘 작동 but 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하긴 어렵다. default boolean removeIf(Predicate

자바가 제공하는 다중 구현 메커니즘 : 인터페이스, 추상 클래스 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상클래스의 하위 클래스가 되어야 한다. 자바는 단일 상속을 지원하기 때문에 추상 클래스 방식은 새로운 타입을 정의하는데 제약 but 인터페이스를 구현한 클래스는 다른 어떤 클래스를 상속했든 간에 같은 타입으로 취급 인터페이스 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다.but 추상 클래스는 그렇지 않다. 새로 추가된 추상 클래스의 모든 자손이 상속구조를 가지게 되며 혼란을 줌. 인터페이스가 요구하는 메서드를 추가하고 implements 구문만 추가하면 된다. 인터페이스는 믹스인에 적절함 : 원래의 주된 타입 외에 특정 선택적 행위를 제공 효과 but 추상 클래스는 그렇..

상속을 고려한 설계와 문서화 1) 메서드를 재정의할때 어떤일이 일어나는지 정확히 정리하여 문서로 남겨라. 상속용 클래스는 재정의할 수 있는 메서드(public, protected 이면서 final이 아닌 메서드)들을 내부적으로 어떻게 이용하는지 문서로 남겨야 한다. 2) 효율적인 하위 클래스를 어려움 없이 만들 수 있게 하기 위해 클래스의 내부 동작 과정 중간에 끼어들 수 있는 훅을 잘 선별하여 protected 메서드 형태로 공개해야 할 수도 있다. 3) 상속용으로 설계한 클래스를 시험하는 방법은 직접 하위 클래스를 만들어보는 것이다. 꼭 필요한 protected 멤버를 놓쳤다면 빈 자리가 드러남, 전혀 쓰이지 않는 protected 멤버는 사실 private 임 등을 알 수 있다. 배포전에 반드시 하..

상속은 코드를 재사용하는 강력한 수단이나 항상 최선은 아니다. 다른 패키지의 구체 클래스를 상속하는 일은 위험하다. 캡슐화를 깨뜨리는 상속 상위 클래스가 어떻게 구현되느냐에 따라 하위 클래스의 동작에 이상이 생길 수 있음 설계자가 확장을 충분히 고려하지 않으면, 하위 클래스는 상위 클래스 변화에 맞춰 수정되어야만 한다. public class InstrumentedHashSet extends HashSet { private int addCount = 0; public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap, loadFactor); } @Override public boolean add(E e) { addCount++; ret..

불변 클래스 그 인스턴스의 내부 값을 수정할 수 없는 클래스 ex)String, 기본 타입 박싱 클래스들, BigInteger, BigDecimal 가변 클래스보다 설계/구현/사용이 쉬움, 오류가 더 적음 불변 클래스를 만들기 위한 규칙 객체의 상태를 변경하는 메서드를 제공하지 않음 클래스를 확장할 수 없음 (하위 클래스에서 객체의 상태를 변하게 만드는 사태를 막기 위함) 모든 필드를 final로 선언 : 여러 스레드에서 접근해도 값이 바뀌지 않음 모든 필드를 private 으로 선언 : 직접 접근해서 수정하지 못하도록 함 자신 외에는 내부의 가변 컴포넌트에 접근할 수 없도록 함 가변 객체를 참조하는 필드가 있다면 클라이언트가 접근하지 못하도록 해야함 접근자 메서드로 반환해서도 안됨. 생성자, 접근자, ..