Inner Class(중첩클래스)

mskimdev·2026년 3월 13일

Java OOP-Advanced

목록 보기
6/8
post-thumbnail

Inner Class (중첩 클래스)

클래스 안에 또 클래스를 선언할 수 있다. 처음 보면 "굳이?"라는 생각이 드는데, 특정 클래스에서만 사용하는 클래스를 밖으로 꺼내지 않고 안에 숨겨두는 것이다. 논리적으로 연관된 것들을 한 곳에 묶어두는 방식이라고 보면 된다.


중첩 클래스의 종류

static 여부와 선언 위치에 따라 4가지로 나뉜다.

1. static 중첩 클래스 (Static Nested Class)

static이 붙은 중첩 클래스다. 바깥 클래스의 인스턴스 없이도 독립적으로 사용할 수 있다.

public class Outer {
    private static String company = "우아한형제들";

    static class Builder {
        private String name;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public String build() {
            return company + " - " + name; // 바깥 클래스의 static 멤버에는 접근 가능
        }
    }
}

// 바깥 클래스 인스턴스 없이 사용 가능
Outer.Builder builder = new Outer.Builder();
System.out.println(builder.name("배달의민족").build()); // 우아한형제들 - 배달의민족

Builder 패턴을 구현할 때 자주 이 형태를 쓴다.

2. 인스턴스 내부 클래스 (Instance Inner Class)

static이 없는 내부 클래스다. 바깥 클래스의 인스턴스에 종속되어 있고, 바깥 클래스의 모든 멤버(private 포함)에 접근할 수 있다.

public class Car {
    private String model = "Tesla";
    private int speed = 0;

    class Engine {
        public void accelerate(int amount) {
            speed += amount; // 바깥 클래스의 private 멤버에 접근 가능
            System.out.println(model + " 현재 속도: " + speed);
        }
    }
}

// 반드시 바깥 클래스 인스턴스를 먼저 만들어야 한다
Car car = new Car();
Car.Engine engine = car.new Engine();
engine.accelerate(50); // Tesla 현재 속도: 50

3. 지역 클래스 (Local Class)

메서드 내부에 선언하는 클래스다. 해당 메서드 안에서만 사용할 수 있다. 자주 쓰이는 형태는 아니지만, 개념으로는 알아두는 게 좋다.

public class Printer {
    public void print() {
        class LocalFormatter {
            String format(String text) {
                return "[" + text + "]";
            }
        }

        LocalFormatter formatter = new LocalFormatter();
        System.out.println(formatter.format("안녕하세요")); // [안녕하세요]
    }
}

4. 익명 클래스 (Anonymous Class)

이름이 없는 클래스다. 클래스를 선언함과 동시에 인스턴스를 생성한다. 주로 인터페이스나 추상 클래스를 일회성으로 구현할 때 쓴다.

public interface Greeting {
    void hello();
}

// 익명 클래스로 인터페이스를 즉석에서 구현
Greeting greeting = new Greeting() {
    @Override
    public void hello() {
        System.out.println("안녕하세요!");
    }
};

greeting.hello(); // 안녕하세요!

Java 8 이후로는 함수형 인터페이스(메서드가 하나인 인터페이스)의 경우 람다식으로 더 간결하게 쓸 수 있다.

// 익명 클래스 대신 람다식으로
Greeting greeting = () -> System.out.println("안녕하세요!");
greeting.hello();

언제 중첩 클래스를 쓸까?

상황추천 방식
바깥 클래스와 논리적으로 강하게 연결되어 있고, 다른 곳에서 쓸 일이 없을 때static 중첩 클래스 또는 내부 클래스
바깥 클래스 인스턴스 없이 독립적으로 써야 할 때 (Builder 패턴 등)static 중첩 클래스
바깥 클래스의 인스턴스 멤버에 자유롭게 접근해야 할 때인스턴스 내부 클래스
인터페이스를 딱 한 번만 구현해서 쓸 때익명 클래스 (또는 람다식)

주의할 점

인스턴스 내부 클래스는 바깥 클래스 인스턴스에 대한 참조를 내부적으로 가지고 있다. 이 때문에 바깥 클래스 인스턴스가 더 이상 필요 없어도 내부 클래스 인스턴스가 살아있으면 GC(가비지 컬렉터)가 메모리를 회수하지 못한다.

바깥 클래스의 인스턴스 멤버에 접근할 필요가 없다면 static 중첩 클래스를 쓰는 것이 메모리 누수 측면에서 안전하다.


마무리

중첩 클래스는 "이 클래스는 여기서만 쓸 거야"라는 의도를 코드로 명확히 표현하는 방법이다. 종류가 많아서 처음엔 헷갈리지만, 가장 자주 마주치는 건 static 중첩 클래스(Builder 패턴)익명 클래스(람다식으로 대체) 두 가지다. 이 둘부터 확실히 이해하고 나머지는 필요할 때 찾아보면 된다.

profile
<- 개발 공부하는 나

0개의 댓글