콘텐츠로 이동

중첩·내부 클래스

내부클래스

내부 클래스(Inner Class): 외부 클래스와 밀접한 관계가 있는 경우 클래스 안에 정의하는 클래스.

목적

  1. 논리적 그룹화
    • 특정 클래스에서만 사용되는 클래스를 내부에 두어 구조를 명확하게 만든다.
  2. 캡슐화
    • 외부에서 접근할 필요 없는 구현을 외부에 노출하지 않는다.
      Human
       └─ Heart
      

종류

종류 특징
정적 중첩 클래스 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 ⭐⭐