중첩 클래스에는 네가지 종류가 있는데, static 맴버 클래스, static이 아닌 맴버 클래스, 익명 클래스, 지역클래스이다. 이 모두를 내부클래스(inner class)라고 한다.

구문적으로 봐선 static과 static이 아닌 맴버 클래스의 유일한 차이점은, static 맴버 클래스의 선언부에 static 수식어가 있다는 것이다. 간단한 예를 들면 이런 것이다.

 static 맴버 클래스  static이 아닌 맴버 클래스
 

public class A{
    private a;

    static class A_1{
    }
    static class A_2{
    }
}
  

public class A{
    private a; 

    class A_1{
    }
    class A_2{
    }
}

구문적으로는 유사하지만 이 두 종류의 중첩 클래스는 많이 다른다.

static이 아닌 멤버 클래스의 각 인스턴스는 자신을 포함하는 외곽 클래스의 인스턴스와 은연 중에 연관이 된다. 따라서 static이 아닌 멤버 클래스의 인스턴스 메소드 내부에서 외곽 클래스의 인스턴스 메소드를 호출하거나, 또는 this 키워드를 사용해서 외곽 클래스의 인스턴스에 대한 참조를 얻을 수 있다.
private static맴버 클래스의 경우 외곽클래스를 나타내는 객체 컴포넌트 표현에 사용하는데 적합다. 불필요하게 외부에 객체 참조를 제공하지 않아 리소스 낭비가 없어진다.
만일 외곽 클래스의 인스턴스를 사용할 필요가 없는 멤버 클래스를 선언한다면, 항상 static 수신자를 선언부에 추가하여 static 맴버 클래스로 만들자.

익명 클래스는 함수 객체를 생성하는데 많이 사용된다. 또한 Runnalbe, Thread, TimerTask 등의 인스턴스와 같은 프로세스 객체를 생성하는데도 많이 사용한다. 그리고 static 팩토리 메소드 내부에서도 사용된다.

지역클래스는 지역 변수가 선언 될 수 있는 곳이면 어디든 선언될 수 있으며, 지역 변수와 동일한 유효 범위를 갖는다. 또한 다른 종류의 중첩 클래스와 동일한 속성을 갖는다. 맴버 클래스처럼 이름을 가질 수 있어 반복적으로 사용될 수 있으며 static이 아닌 상황일 때에 한해서 익명 클래스 처럼 외곽 인스턴스를 가지며 static 멤버를 포함할 수 없다.

만일 중첩 클래스가 메소드 외부에서 접근할 필요가 있거나 코드가 너무 길어서 메소드 내부에 두기 적합하지 않다면 멤버 클래스를 사용하자. 만일 멤버 클래스의 각 인스턴스가 외곽 클래스의 인스턴스를 참조할 필요가 있다면 static 이 아닌 멤버 클래스로 만들고 그렇지 않다면 static으로 만든다. 클래스가 어떤 메소드 내부에 속한다는 가정하에, 만일 한 곳에서만 그 클래스의 인스턴스를 생성할 필요가 있고 그 클래스의 특성을 나타내는 타입이 이미 존재한다면, 익명 클래스로 만들고 그렇지 않으면 지역클래스로 만든다.
Posted by 서오석
,