▶ 중첩 클래스 및 중첩 인터페이스를 사용하는 이유


- 자바는 객체 지향 프로그램으로 각 클래스가 관계를 맺으며 상호작용을 한다. 어떤 클래스는 많은 클래스와 상호작용을 하기도 하지만, 다른 어떤 클래스는 특정 클래스하고만 상호작용을 하기도 한다. 여러 클래스와 상호작용을 할 때는 해당 클래스를 독립적으로 생성하는 것이 좋지만, 특정 클래스하고만 상호작용을 할 경우 특정 클래스 내부에 해당 클래스를 생성하는 것이 효율적이다.


- 중첩 인터페이스는 해당 클래스와 깊은 상호작용을 하는 구현 클래스를 생성하기 위해 사용된다.




▶ 중첩 클래스(Nested Class)


- 하나의 클래스 내부에 선언된 다른 클래스를 의미한다. 즉, 포함되어지는 클래스이다.


- 두 클래스의 멤버간에 접근이 용이하다. 중첩 클래스는 자신을 포함하는 클래스의 모든 멤버에 접근할 수 있다. 즉, 접근 제한자가 private인 멤버라 할지라도 중첩 클래스는 접근할 수 있다.


- 불필요한 상호작용을 맺은 클래스들을 외부로부터 감춤으로써 코드가 간결해진다.



class ClassName {

class NestedClassName {

...

}

}





▶ 멤버 클래스


- 클래스의 멤버로서 선언되는 중첩 클래스


- 해당 클래스나 객체가 사용 중일 경우 재사용이 가능하다.


- 멤버 클래스도 하나의 클래스이기 때문에 컴파일하면 바이트 코드 파일(~.class)가 생성된다.


멤버 클래스의 바이트 코드 파일 이름 : 바깥클래스명$ 멤버클래스명.class

로컬 클래스의 경우 : 바깥클래스명$1 로컬클래스명.class


- 인스턴스 멤버 클래스


class A {

class B { ... } // A객체를 생성해야 B 중첩 클래스(인스턴스 멤버 클래스)를 사용할 수 있다.

}


  • 중첩 클래스를 포함한 클래스를 생성해야만 해당 중첩 클래스를 사용할 수 있다.
  • 정적 필드와 메소드는 선언할 수 없다.
  • 외부 클래스에서 인스턴스 멤버 클래스를 생성하려면 바깥 클래스를 먼저 선언(객체 생성)해야 한다.
- 정적 멤버 클래스


class A {

static class B { ... } // A 클래스로 바로 접근 가능한 B 중첩 클래스(정적 멤버 클래스)

}


  • 중첩 클래스를 포함한 클래스로 바로 접근 가능한 중첩 클래스
  • 모든 종류의 필드와 메소드를 선언할 수 있다.
  • 바깥 객체를 생성하지 않아도 바로 정적 멤버 클래스를 이용할 수 있다.



▶ 로컬 클래스

- 메소드 내부에서 선언된 중첩 클래스

- 메소드 실행 시에만 사용되며, 메소드가 종료되면 사라진다.

- 로컬 클래스는 접근 제한자(public, private, protected) 및 static을 붙일 수 없다. 메소드 내부에서 사용되므로 접근을 제한할 필요가 없기 때문이다.

- 정적 필드와 메소드를 선언할 수 없다.

- 로컬 클래스가 선언된 메소드는 new 연산자를 통해 객체를 생성해야 해당 로컬 클래스를 사용할 수 있다.

- 다음과 같이 비동기 처리를 위한 스레드 객체 생성 시 사용된다.

void method() {

class DownloadThread extends Thread { ... } //로컬 클래스

DownloadThread th = new DownloadThread(); // 선언과 초기화 필수

th.start();

}





▶ 중첩 클래스의 접근 제한


- 멤버 클래스

  • 인스턴스 멤버 클래스는 바깥 클래스의 인스턴스 필드를 통해 객체를 생성하거나 인스턴스 메소드 내부에서 객체를 생성할 수 있지만 정적 필드나 메소드는 해당되지 않는다. 즉, 바깥 클래스의 정적 멤버에 포함될 수 없다.
  • 인스턴스 멤버 클래스 내부에서 바깥 클래스로 접근할 때 모든 필드와 메소드가 가능하다. 즉, 바깥 클래스의 정적 멤버에 접근가능하다.
  • 정적 멤버 클래스는 바깥 클래스의 모든 필드의 초기값으로 혹은 모든 메소드에서 객체를 생성할 수 있다.
  • 정적 멤버 클래스 내부에서는 바깥 클래스의 정적 필드와 메소드에만 접근할 수 있다. 즉, 바깥 클래스의 인스턴스 멤버에 접근할 수 없다.

- 로컬 클래스
  • 로컬 클래스 내부에서는 바깥 클래스로 제한 없이 접근할 수 있다.
  • 로컬 클래스에서 사용되는 매개변수와 로컬 변수는 모두 final 특성(최종값)을 갖는다.
☞ 로컬 클래스의 객체는 메소드 실행이 끝나도 힙 메모리에 남아있으므로 사용할 수 있지만, 메소드의 매개변수 및 로컬변수는 메소드 실행이 끝나면 사라지므로 로컬 객체에서 사용할 경우 에러가 발생한다. 해결 방법으로 컴파일 시 로컬 클래스에서 사용하는 매개변수 및 로컬변수는 로컬 클래스 내부의 기억장소에 두고 사용한다. 그러나 값이 수정되면 복사해 둔 기억장소가 변경되므로 이 문제를 해결하고자 변수를 final로 선언하여 수정을 맞는다. 쉽게 말해, final 로 선언된 매개변수와 로컬변수만 로컬 클래스에서 사용가능하다. 자바 8부터는 final 키워드 없이 선언되어도 여전히 값을 수정할 수 없는 final 특성을 갖는다.

☞ final 키워드의 존재 여부의 차이점은 로컬 클래스의 복사 위치이다. final 키워드가 있을 경우 로컬 클래스를 포함한 메소드 내부에서 지역 변수로 복사된다. 없을 경우 로컬 클래스의 필드로 복사된다.


- 중첩 클래스 내부에서 바깥 클래스의 객체 참조를 얻으려면 아래와 같이 선언해야한다.

바깥클래스명.this.필드명;

바깥클래스명.this.메소드명;




▶ 중첩 인터페이스(Nested Interface)


- 클래스의 멤버로 선언된 인터페이스


- 주로 UI(User Interface) 프로그래밍에서 이벤트를 처리할 때 사용된다. 즉 해당 이벤트를 처리하는 구현 클래스를 만드는 것이다.


class ClassName {

interface NestedInterfaceName {

...

}

}







+ Recent posts