중첩·내부 클래스
내부클래스
내부 클래스(Inner Class): 외부 클래스와 밀접한 관계가 있는 경우 클래스 안에 정의하는 클래스.
목적
- 논리적 그룹화
- 특정 클래스에서만 사용되는 클래스를 내부에 두어 구조를 명확하게 만든다.
- 캡슐화
- 외부에서 접근할 필요 없는 구현을 외부에 노출하지 않는다.
종류
| 종류 |
특징 |
| 정적 중첩 클래스 |
static 클래스 |
| 내부 클래스 |
외부 인스턴스에 종속 |
| 지역 클래스 |
메서드 내부 선언 |
| 익명 클래스 |
이름 없는 클래스 |
정적 중첩 클래스 (Static Nested Class)
특징
- static 클래스
- 외부 클래스 인스턴스와 무관
- 외부 클래스의 static 멤버만 접근 가능
- 일반 static 클래스처럼 사용
구조
Outer.Inner inner = new Outer.Inner();
예제
class Human {
private static int outClassValue = 3;
private int outInstanceValue = 2;
static class Heart {
private int innerInstanceValue = 1;
public void print() {
// 내부 클래스 변수
System.out.println(innerInstanceValue);
// 외부 static 변수 접근 가능
System.out.println(outClassValue);
// 외부 인스턴스 변수 접근 불가
// System.out.println(outInstanceValue); // 컴파일 에러
}
}
}
사용 예시
Human.Heart heart = new Human.Heart();
heart.print();
중첩클래스 or 내부 클래스 (Non-static Inner Class)
특징
- 외부 클래스 인스턴스에 종속
- 외부 클래스 모든 멤버 접근 가능
- 생성 시 외부 객체 필요
생성 방식
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
예제
class Human {
private static int outClassValue = 3;
private int outInstanceValue = 2;
class Heart {
private int innerInstanceValue = 1;
public void print() {
System.out.println(innerInstanceValue);
// 외부 인스턴스 변수 접근 가능
System.out.println(outInstanceValue);
// 외부 static 변수 접근 가능
System.out.println(outClassValue);
}
}
}
사용
Human human = new Human();
Human.Heart heart = human.new Heart();
주의사항
- 내부 클래스는 외부 객체를 참조한다.
Inner → Outer 참조
문제: Inner 객체가 오래 살아있으면 Outer 객체도 GC 대상이 되지 않음 (메모리 누수)
해결: Inner class 대신 Static nested class 사용 권장
지역 클래스 (Local Class)
특징
- 메서드 내부에 선언
- 해당 메서드 안에서만 사용 가능
- 지역 변수 캡처 가능
캡처 변수 특징
- final 또는 effectively final
- 값 변경 불가
메서드 종료 후에도 내부 객체가 사용될 수 있기 때문
예제
class LocalOuter {
private int outerVar = 3;
public Printer process(int paramVar) {
final int localVar = 1;
class Inner implements Printer {
@Override
public void print() {
int value = 0;
System.out.println(value);
System.out.println(localVar);
System.out.println(paramVar);
System.out.println(outerVar);
}
}
return new Inner();
}
}
사용
LocalOuter outer = new LocalOuter();
Printer printer = outer.process(2);
printer.print();
접근 가능 변수
| 변수 |
접근 가능 |
| 지역 변수 |
O (final) |
| 파라미터 |
O (final) |
| 외부 인스턴스 변수 |
O |
| 외부 static 변수 |
O |
익명 클래스 (Anonymous Class)
특징
- 이름 없는 클래스
- 한 번만 사용할 때 사용
- 선언과 동시에 구현
사용
Interface obj = new Interface() {
// 구현
};
예시
class AnonymousOuter {
public void process() {
Printer printer = new Printer() {
@Override
public void print() {
System.out.println("TEST");
}
};
printer.print();
}
}
전체 비교
| 구분 |
외부 인스턴스 필요 |
static 접근 |
사용 빈도 |
| 정적 중첩 클래스 |
X |
O |
⭐⭐⭐⭐ |
| 내부 클래스 |
O |
O |
⭐ |
| 지역 클래스 |
O |
O |
⭐ |
| 익명 클래스 |
O |
O |
⭐⭐ |