중첩 클래스
•
중첩 클래스(nested class)는 다른 클래스 안에 정의된 클래스를 의미하는데, 중첩 클래스는 자신을 감싼 바깥 클래스에서만 사용되어야 하며 그외에 사용되는 곳이 있다면 톱레벨 클래스로 만들어야한다.
•
중첩 클래스에는 정적 멤버 클래스, 비정적 멤버 클래스, 익명 클래스, 지역 클래스가 있다.
정적 멤버 클래스
•
정적 멤버 클래스는 바깥 클래스의 private 필드에 접근할 수 있다는 점만 제외하고 일반 클래스와 같다.
•
접근 제한자 규칙도 다른 정적 멤버와 동일한 규칙을 적용받는다.
•
private 정적 멤버 클래스는 바깥 클래스의 구성요소를 나타낼 때 주로 사용된다.
비정적 멤버 클래스
•
비정적 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결되기 때문에, 비정적 멤버 클래스의 인스턴스 메서드에서 정규화된 this(바깥클래스명.this)를 사용해 바깥 인스턴스의 메서드를 호출하거나 참조할 수 있다.
•
이러한 이유로 중첩 클래스의 인스턴스가 개념상으로 바깥 인스턴스와 독립적으로 존재할 수 있다면, 중첩 클래스를 정적 멤버 클래스로 선언해야한다.
•
비정적 멤버 클래스는 어떤 클래스의 인스턴스를 감싸 다른 클래스의 인스턴스처럼 보이게하는 뷰로 사용하는 방식인 어댑터를 정의할 때 자주 쓰인다. 예시를 들면, Map 인터페이스의 구현체들은 자신의 컬렉션 뷰를 구현할 때 비정적 멤버 클래스를 사용한다.
public class MySet<E> extends AbstractSet<E> {
...
@Override
public Iterator<E> iterator() {
return MyIterator();
}
private class MyIterator implements Iterator<E> {
...
}
}
Java
복사
멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 사용하자
•
static을 생략하면 바깥 인스턴스로의 숨은 외부 참조를 가져, 시간과 공간이 소비되고 가비지 컬렉션이 바깥 클래스의 인스턴스를 수거하지 못해 메모리 누수가 발생할 수 있다.
•
이런 참조는 암묵적으로 연결되기 때문에, 눈에 잘 보이지 않아 문제의 원인을 찾기 어렵다.
익명 클래스
•
익명 클래스를 사용하면 쓰이는 시점에 선언과 동시에 인스턴스가 만들어지고 사용 후 소멸되기 때문에, 바깥 클래스의 멤버가 아니다.
•
오직 비정적 문맥에서 사용될 때만 바깥 클래스의 인스턴스를 참조할 수 있다. 정적 문맥에서도 상수 변수 이외의 정적 멤버는 가질 수 없다.
•
익명 클래스는 선언한 지점에서만 인스턴스를 만들 수 있고, instanceof 검사를 할 수 없으며, 여러 인터페이스를 구현할 수 없고, 인터페이스를 구현하면서 다른 클래스를 상속하는 것도 안된다.
•
Java에서는 람다 전에 작은 함수 객체나 처리 객체를 만드는데 주로 사용했으나, 람다 적용 이후로는 그런 부분은 람다를 적용해 사용하며 익명 클래스는 정적 팩터리 메서드를 구현할 때나 사용된다.
지역 클래스
•
지역 변수를 선언할 수 있는 곳에 클래스를 선언하여, 멤버 클래스처럼 이름이 있고 반복해서 사용할 수 있지만 익명 클래스처럼 비정적 문맥에서 사용될 때만 바깥 인스턴스를 참조할 수 있고 정적 멤버를 가질 수 없다.
•
지역 클래스는 가독성을 위해 짧게 작성해야하고, 네 가지 중첩 클래스 중에 가장 드물게 사용된다.