아이템 22. 멤버 클래스는 가능하면 static으로 선언하라.

22. 멤버 클래스는 가능하면 static으로 선언하라.

중첩 클래스에는 네 가지 종류가 있다.

  1. 정적 멤버 클래스(static member class) : 정적 멤버 클래스는 바깥 클래스의 모든 멤버(심지어 private 필드 까지도) 접근 가능하다.
  2. 비 정적 멤버 클래스(nonstatic member class) : 비 정적 멤버 클래스 객체와 바깥 객체와의 연결은 비-정적 멤버 클래스의 객체가 만들어지는 수간에 확립되고, 그 뒤에는 변경할 없다.
  3. 익명 클래스(anonymous class) : 선언 하는 그 순간에만 객체가 생각됨, 표현식들 중간에 등장하는 경우가 많기 때문에 짧게 작성(10줄 내외)하는 것이 좋음
  4. 지역 클래스(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)을 깨지 않고는 다음 릴리스에서 비 정적 멤버 클래스를 정적 멤버 클래스로 바꿀 방법이 없다.