JAVA
중첩 클래스(Nested Class)와 중첩 인터페이스(Nested Interface)
hohahihi
2023. 3. 10. 12:00
중첩 클래스
클래스 내부에 선언된 다른 클래스
- 특정 클래스만 관계를 맺을 경우에 사용
- 클래스의 멤버 사용이 편리하다.
- 외부에서는 중첨 관계의 클래스를 감춤으로써 코드의 복잡성을 줄일 수 있다.
- 바깥 클래스를 컴파일하면 중첩 클래스에 대한 별도의 바이트코드 파일(.class)이 생성된다.
중첩 클래스의 바이트코드 파일은 "$" 앞에 외부 클래스가 기록된다.
바깥클래스명$중첩클래스명.class

인스턴스 멤버 클래스
클래스의 인스턴스 멤버로 선언된 중첩 클래스
class 외부클래스 {
[public | private] class 멤버클래스 { ... }
}
|
- 일반적으로 private 접근 제한으로 설정하여 바깥 클래스 내부에서만 사용한다.
- 객체 생성은 바깥 클래스의 인스턴스 필드 값, 생성자, 인스턴스 메소드에서 가능하다.
public class A {
//인스턴스 멤버 클래스
class B {}
//인스턴스 필드 값으로 B 객체 대입
B field = new B();
//생성자
A() {
B b = new B();
}
//인스턴스 메소드
void method() {
B b = new B();
}
}
|
- 바깥 클래스 객체가 먼저 생성되어야 객체를 생성할 수 있다.
A a = new A();
A.B b = a.new B();
|
- 인스턴스 멤버 클래스는 일반 클래스와 동일한 멤버(필드, 생성자, 메소드)를 가질 수 있다.
단, 정적 필드와 정적 메소드는 Java 17부터 지원한다.
정적 멤버 클래스
클래스 내부에 static 키워드로 선언된 중첩 클래스
class 외부클래스 {
[public | private] static class 멤버클래스 { ... }
}
|
- 바깥 클래스 외부에서 사용되는 경우가 많아서 주로 default 또는 public 접근 제한을 부여한다.
- 정적 멤버 클래스 객체는 바깥 클래스의 내부 어디든지 생성할 수 있다.
public class A {
//인스턴스 멤버 클래스
static class B {}
//인스턴스 필드 값으로 B 객체 대입
B field1 = new B();
//정적 필드 값으로 B 객체 대입
static B field2 = new B();
//생성자
A() {
B b = new B();
}
//인스턴스 메소드
void method1() {
B b = new B();
}
//정적 메소드
static void method2() {
B b = new B();
}
}
|
- 외부에서 선언된 클래스 객체를 생성하지 않고 객체를 생성할 수 있다.
A.B b = new A.B();
|
로컬 클래스
생성자 또는 메소드 내부에 선언된 중첩 클래스
class 바깥클래스 {
리턴타입 메소드() {
class 로컬클래스 { ... }
}
}
|
- 클래스를 선언한 생성자 또는 메소드가 실행될 때만 객체를 생성할 수 있다.
- 로컬 클래스도 필드, 생성자, 메소드를 가질 수 있다.
정적 필드와 정적 메소드는 Java 17부터 지원
//바깥 클래스
public class A {
//메소드
void useB() {
//로컬 클래스
class B {
//인스턴스 필드
int field1 = 1;
//정적 필드(Java 17부터 허용)
static int field2 = 2;
//생성자
B() {
System.out.println("B-생성자 실행");
}
//인스턴스 메소드
void method1() {
System.out.println("B-method1 실행");
}
//정적 메소드(Java 17부터 허용)
static void method2() {
System.out.println("B-method2 실행");
}
}
//로컬 객체 생성
B b = new B();
//로컬 객체의 인스턴스 필드와 메소드 사용
System.out.println(b.field1);
b.method1();
//로컬 클래스의 정적 필드와 메소드 사용(Java 17부터 허용)
System.out.println(B.field2);
B.method2();
}
}
|
로컬 변수
- 생성자나 생성자 내부, 메소드의 매개변수 또는 메소드 내부에서 선언된 변수
- 로컬 클래스 내부에서 로컬 변수는 final 특성을 갖게 되어 값을 변경할 수 없다.
Java 7 이전에는 final 키워드 필수
Java 8 이후부터 final 키워드 생략 가능(final 특성을 가진다는 것을 명시하기 위해 사용)
바깥 멤버 접근
바깥 클래스의 멤버 접근 제한
종류 | 정적 필드 | 정적 메소드 | 인스턴스 필드 | 인스턴스 메소드 |
인스턴스 멤버 클래스 | O | O | O | O |
정적 멤버 클래스 | O | O | X | X |
- 정적 멤버 클래스는 바깥 객체가 없어도 사용 가능해야 하므로 바깥 클래스의 인스턴스 멤버는 접근할 수 없다.
바깥 클래스의 객체 접근
- 중첩 클래스 내부에서 this는 해당 중첩 클래스 객체를 의미함.
- 바깥 클래스 객체는 바깥 클래스 이름까지 명시한 this로 호출한다.
//바깥 클래스 A
public class A {
//A 인스턴스 필드 선언
String field = "A class";
//A 인스턴스 메소드 선언
void method(String field) {
//A 인스턴스 필드 호출
System.out.println(this.field);
System.out.println(field);
}
//인스턴스 멤버 클래스 A
class B {
//B 인스턴스 필드 선언
String field = "B class";
//B 인스턴스 메소드 선언
void method() {
//A 인스턴스 메소드와 B 인스턴스 필드 호출
A.this.method(this.field);
}
}
}
|
중첩 인터페이스
클래스의 멤버로 선언된 인터페이스
- 해당 클래스와 긴밀한 관계를 맺는 구현 객체를 만들기 위해 사용
class A {
[public | private] [static] interface B {
//상수 필드
//추상 메소드
//디폴트 메소드
//정적 메소드
}
}
|
- 안드로이드를 포함한 UI 프로그램에서 이벤트를 처리할 때 많이 사용