아이템 22. 멤버 클래스는 가능하면 static으로 선언하라.
22. 멤버 클래스는 가능하면 static으로 선언하라.
- 중첩 클래스(nested class)는 다른 클래스 안에 정의된 클래스(멤버 클래스)다.
- 중첨 클래스는 해당 클래스가 속한 클래스 안에서만 사용된다.
중첩 클래스에는 네 가지 종류가 있다.
- 정적 멤버 클래스(static member class) : 정적 멤버 클래스는 바깥 클래스의 모든 멤버(심지어 private 필드 까지도) 접근 가능하다.
- 비 정적 멤버 클래스(nonstatic member class) : 비 정적 멤버 클래스 객체와 바깥 객체와의 연결은 비-정적 멤버 클래스의 객체가 만들어지는 수간에 확립되고, 그 뒤에는 변경할 없다.
- 익명 클래스(anonymous class) : 선언 하는 그 순간에만 객체가 생각됨, 표현식들 중간에 등장하는 경우가 많기 때문에 짧게 작성(10줄 내외)하는 것이 좋음
- 지역 클래스(local class)
비 정적 멤버 클래스 안에서는 바깥 클래스의 메서드를 호출하 수도 있고 this한정 구문을 통해 바깥객체에 대한 참조를 획득할 수도 있다.
// this 한정 구분(qualified this)은 바깥 객체를 참조하기 위해 this앞에 바깥 객체의 자료형 이름을 붙이는 것을 의미함
class Envelope {
public void x() { System.out.println("helo"); }
class Enclosure {
void x() { Envelope.this.x(); /* 바깥 클래스(Envelope)에 한정됨 */ }
}
}
Set이나 List같은 컬렉션 클래스를 구현하는 클래슨느 비 정적 멤버 클래스를 사용해 반복자(interator)를 구현한다. 다음은 비 정적 멤버 클래스의 전형적인 용례이다.
public class MySet<E> extends AbstractSet<E> {
public Iterator<E> iterator(){
return new MyIterator();
}
private class MyIterator implements Iterator<E> {
/// MySet 전용 Iterator 구현
}
}
바깥 클래스 객체에 접근할 필요가 없는 멤버 클래스를 정의할 때는 항상 선언 문앞에 static을 붙여 비 정적 멤버 클래스 대신 정적 멤버 클래스로 만들자.
멤버 클래스가 API 클래스의 public이나 protected 멤버인 경우에는, 정적 멤버 클래스로 만들 것인지 아니면 비 정적 멤버 클래스로 만들 것인지가 더욱 중요하다. 일단 API에 포함되고 나면, 이진 호환성(binary compatibility)을 깨지 않고는 다음 릴리스에서 비 정적 멤버 클래스를 정적 멤버 클래스로 바꿀 방법이 없다.