중첩 클래스란 다른 클래스 안에 정의된 클래스를 말한다.
중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야 하며, 그 외의 쓰임새가 있다면 톱레벨 클래스로 만들어야 한다.
중첩 클래스는 정적 멤버, 비정적 멤버, 익명, 지역 클래스 네가지이다.
이 중 첫번째를 제외한 나머지는 내부 클래스에 해당한다.
- 정적 멤버 클래스
- 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스
- 비정적 멤버 클래스
- 바깥 클래스의 인스턴스와 암묵적으로 연결된다.
- 어댑터를 정의할 때 자주 쓰인다.
- 멤버 클래스에서 바깥 인스턴스를 참조할 필요가 없다면 무조건 정적 멤버 클래스로 만들자.
- 익명 클래스
- 바깥 클래스의 멤버가 아니며, 쓰이는 시점과 동시에 인스턴스가 만들어진다.
- 비정적인 문맥에서 사용될 때만 바깥 클래스의 인스턴스를 참조할 수 있다.
- 자바에서 람다를 지원하기 전에 즉석에서 작은 함수 객체나 처리 객체를 만들 때 사용했다.
- 정적 팩터리 메서드를 만들 때 사용할 수도 있다.
- 지역 클래스
- 가장 드물게 사용된다.
- 지역 변수를 선언하는 곳이면 어디든 지역 클래스를 정의해 사용할 수 있다.
- 가독성을 위해 짧게 작성해야 한다.
정적 멤버 클래스는 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다는 점만 제외하고는 일반 클래스와 같다.
정적 멤버 클래스는 흔히 바깥 클래스와 함꼐 쓰일 때만 유용한 public 도우미 클래스로 쓰인다.
계산기가 지원하는 연산 종류를 정의하는 열거타입을 예로,
Operation 열거 타입은 Calculator클래스의 public 정적 멤버 클래스가 되어야 한다.
그러면 Calculator의 클라이언트에서 Calculaotr.Operation.PLUS나 MINUS같은 형태로 원하는 연산을 참조할 수 있다.
정적과 비정적 멤버의 차이는 단지 static이지만 의므는 꽤 크다.
비정적 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결된다.
그래서 비정적의 인스턴스 메서드에서 정규화된 클래스명.this를 사용해 바깥클래스의 메서드를 호출하거나 참조를 가져올 수 있다.
비정적 멤버 클래스는 어댑터 패턴을 정의할 때 자주 쓰인다.
즉, 어떤 클래스의 인스턴스를 감싸 마치 다른 클르새의 인스턴스처럼 보이게 하는 뷰로 사용하는 것이다.
Map인터페이스의 구현체들이 자신의 컬렉션 뷰를 구현할 때 비정적 멤버 클래스를 사용한다.
public class MySet<E> extends AbstractSet<E>{
@Override public Iterator<E> iterator(){
return new MyIterator();
}
private class MyIterator implements Iterator<E>{
...
}
}
멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자.
static을 생략하면 바깥 인스턴스로의 숨은 외부 참조를 갖게 되기 때문에 시간과 공간이 소비된다.
참조로 인해 GC가 수집하지 못해 메모리 누수가 생길수도 있다.
익명 클래스와 지역 클래스의 설명은 생략하겠다.
1. 멤버 클래스를 static으로 만드는 이유는?
멤버 클래스가 바깥 클래스를 접근할 일이 없다면 static을 붙여 정적 클래스로 만드는 것이 좋다.
바깥 클래스의 인스턴스를 참조하지 않기 때문에 자원 소모를 줄일 수 있고 참조로 인해 GC 수집이 불가능해 질 때의
메모리 누수를 방지할 수 있다.
객체 간의 결합도를 낮추고 바깥 클래스의 인스턴스없이 사용할 수 있는 유틸리티 클래스로 활용 할 수도 있다.
'JAVA > 이펙티브 자바' 카테고리의 다른 글
26. 로 타입을 사용하지 말라 ( 제네릭, 타입 안정성 ) (0) | 2023.07.10 |
---|---|
25. 톱레벨 클래스는 한 파일에 하나만 담으라 (0) | 2023.07.10 |
23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 ( 클래스 계층구조 ) (0) | 2023.07.06 |
22. 인터페이스는 타입을 정의하는 용도로만 사용하라 ( 상수 공개 ) (0) | 2023.07.06 |
21. 인터페이스는 구현하는 쪽을 고려해 설계해라( default 메서드) (0) | 2023.07.06 |