inner class(중첩클래스)

Kim taegwan·2026년 3월 29일

1. 내부 클래스란? (inner class)

자바에서 내부 클래스(Inner Class)는 한 클래스 내부에 선언된 클래스를 말합니다. 내부 클래스를 선언하게 되면 내부 클래스와 외부 클래스라고 표현할 수 있습니다. 내부 클래스는 보통 외부 클래스와 연관이 있는 경우가 많고 다른 곳에서 거의 사용할 일이 없는 경우에 내부 클래스를 선언해서 활용을 합니다.

package innerclass;

public class OuterClass1 {

    private int num = 10;
    // 클래스 파일안에 내부에 또 클래스 선언 (중첩클래스) // 인스턴스 내부 클래스
    class InnerClass {
        public void display() {
            System.out.println("num : " + num);
        }
    }
} // end of outer class
package innerclass;

public class Main1 {

    public static void main(String[] args) {
        // 내부 클래스가 일반 멤버 클래스로 설계된 경우
        // 외부 클래스 객체가 생성되고 내부 클래스를 생성할 수 있다.
        OuterClass1 outerClass = new OuterClass1();
        OuterClass1.InnerClass innerClass = outerClass.new InnerClass();
        innerClass.display();
    }
}

중첩 클래스는 “클래스 안에 들어있는 클래스”이고, 네 예제의 내부 클래스는 바깥 객체에 붙어서 생성되며 바깥 클래스의 멤버를 쉽게 사용할 수 있는 구조야.
즉 바깥 클래스가 생성이 되야 내부클래스를 생성할 수 있다.


2. 내부 클래스의 종류

  1. 멤버 내부 클래스(Member Inner Class): 외부 클래스의 필드와 같은 위치에 선언되며, 외부 클래스의 인스턴스에 종속적입니다. 멤버 내부 클래스의 인스턴스는 외부 클래스의 인스턴스가 있어야 생성할 수 있습니다.
  2. 정적 내부 클래스(Static Inner Class): 외부 클래스의 필드에 선언되지만, static 키워드를 사용하여 선언됩니다. 정적 내부 클래스는 외부 클래스의 인스턴스와 독립적으로 존재할 수 있으며, 주로 관련 있는 클래스들을 논리적으로 그룹화할 때 사용됩니다.
  3. 지역 내부 클래스(Local Inner Class): 메서드 내부에 선언되며, 선언된 메서드 내에서만 사용됩니다. 지역 내부 클래스는 해당 메서드의 지역 변수와 마찬가지로 스코프가 제한됩니다.
  4. 익명 내부 클래스(Anonymous Inner Class): 이름이 없는 내부 클래스로, 주로 인터페이스나 추상 클래스를 간편하게 구현할 때 사용됩니다. 익명 내부 클래스는 오직 하나의 인스턴스만 생성할 수 있으며, 주로 이벤트 처리나 콜백 구현에 사용됩니다.
package innerclass;

public class OuterClass2 {
    private static int num = 10;
    // 정적 내부 클래스
    static class InnerClass {
        public void display() {
            System.out.println("num : " + num);
        }
    }
} // end of outer class

지금 정적 내부클래스가 num에 접근 할 수 있는 이유는 num도 정적 변수이기 때문이다.

package innerclass;

public class Main2 {

    public static void main(String[] args) {
        // 경우1
        // Inner Class 일반 멤버 클래스로 설계된 경우
        // 인스턴스 내부 클래스(기본)
        // - 외부 클래스와 강하게 연결됨 상태
        // - 외부 객체가 있어야 내부 객체를 호출할 수 있음.

        // 경우 2
        // static Inner Class 정적 클래스로 설계된 경우
        // - 외부 클래스와 이름만 묶인 상태
        // - 외부 객체 생성없이도 생성 가능
        OuterClass2.InnerClass inner = new OuterClass2.InnerClass();
        inner.display();

    }
}
OuterClass1 outer = new OuterClass1();
OuterClass1.InnerClass inner = outer.new InnerClass();
일반 멤버 내부클래스에서는 이렇게 생성을 했었는데
OuterClass2.InnerClass inner = new OuterClass2.InnerClass();

정적 내부클래스는 이렇게 바로 생성할 수 있다.

package innerclass;

// 정적 내부 클래스 연습
public class Spaceship {

    private Engine engine;

    // 엔진을 추가한다
    public void addEngine(Engine engine) {
        this.engine = engine;
    }

    public void startSpaceShip() {
        if(engine == null) {
            System.out.println("엔진을 먼저 장착해주세요");
        } else {
            System.out.println("우주여행을 출발 합니다");
        }
    }

    // 논리적으로 강하게 그룹화 시킬 때 내부 클래스를 사용할 수 있다.
    // 정적 내부 클래스 engine
    public static class Engine {

        private static int engineCount = 0;
        private int serialNumber;

        public Engine() {
            this.serialNumber = ++engineCount;
        }

        public void start() {
            System.out.println("Engine " + serialNumber + " 동작 합니다");
        }
    } // end of inner static class

}
package innerclass;

public class SpaceshipMain {

    public static void main(String[] args) {

        // 정적 내부클래라서 바로 생성 가능함
        Spaceship.Engine engine1 = new Spaceship.Engine();
        Spaceship spaceship = new Spaceship();
        spaceship.addEngine(engine1);
        spaceship.startSpaceShip();

    } // end of main
}

이렇게 정적 내부클래스를 쓸 수 있다.


  1. 지역 내부 클래스(Local Inner Class)
package innerclass;

// 지역 내부 클래스(Local inner class)
public class OuterClass3 {
    public void display() {
        // 메서드 안에 클래스를 선언
        class LocalInnerClass {
            void printMessage() {
                System.out.println("지역 내부 클래스의 메서드");
            }
        } // 지역 내부 클래스

        // 지역 내부 클래스의 인스턴스 생성
        LocalInnerClass innerClass = new LocalInnerClass();
        innerClass.printMessage();
    }
}

지역 내부 클래스는 특정 메서드 내에서만 정의되고 사용되는 클래스로, 메서드 실행 시에만 존재하고 메서드의 지역 변수처럼 동작합니다. 이 클래스는 외부에서는 접근할 수 없으며, 주로 메서드 내에서 일회성 작업을 수행하는 객체를 생성할 때 유용 합니다.

package innerclass;

public class Main3 {

    public static void main(String[] args) {
        OuterClass3 outerClass3 = new OuterClass3();
        outerClass3.display();

    } // end of main
}

이렇게 외부에서는 바로 접근은 못하게 display메서드를 실행해서 안에 localinnerclass가 정의가 되고 그다음 밑에서 객체를 생성하여 printmessage메서드를 호출하고 있는 모습이다.
지역 내부클래스는 내부에서 생성하고 실행되어야 하기에 이렇게 실행하는 모습이다.
display() 안에서 잠깐 정의된 지역 내부 클래스는
그 메서드 바깥으로 못 나와.

  1. 익명 내부 클래스 (익명이란? 이름이 없다 라는 의미 입니다.)
package innerclass;

// 익명 내부클래스 사용해 보기
public class OuterClass4 {
    // 1.
    Runnable runnable; // 인터페이스
    // 1.
    public OuterClass4() {
       // 인터페이스를 구현 익명 클래스로 생성시킬 수 있다.
       // 내부에서 추상 메서드를 일반 메서드로 재 정의해서 마치 실제 클래스 처럼 구현해서 사용할 수 있다.
        new Runnable() {
            @Override
            public void run() {
                //...
            }
        };
    } // end of 생성자

    // 2.
    // 멤버 변수 선언과 동시에 인터페이스를 구현 클래스로 동시에 초기화
    Runnable runnable2 = new Runnable() {
        @Override
        public void run() {

        }
    };

}

원래는 클래스를 만들고 상속하여 객체를 생성했는데 익명클래스는
변수 선언과 동시에 인터페이스를 구현 클래스로 동시에 총기화하여 만들었다.

class 이름없는클래스 implements Runnable {
    @Override
    public void run() {
        System.out.println("실행");
    }
}
Runnable runnable2 = new 이름없는클래스();

내부적으로는 이렇게 이루어 지고 있는 것이다.

0개의 댓글