[Java]내부 클래스 정리

2026. 4. 22. 10:41·Language/Java

* 개념 복습과 학습 정도를 파악하고자 포스팅합니다

 

내부 클래스(Inner Class)

1. 내부 클래스?

클래스 안에 정의된 클래스.

두 클래스가 긴밀하게 연관될 때 하나를 다른 하나의 내부에 정의해서 논리적으로 묶습니다.

class Outer {           // 외부 클래스
    class Inner {       // 내부 클래스
        // ...
    }
}

 

내부 클래스를 쓰는 이유는 세 가지가 있어요.

  • 캡슐화 강화: 외부에 노출할 필요 없는 클래스를 숨길 수 있습니다.
  • 코드 구조화: 관련된 클래스를 논리적으로 묶어 가독성을 높여요.
  • 외부 멤버 접근: 내부 클래스는 외부 클래스의 private 멤버에서 자유롭게 접근할 수 있습니다.

내부 클래스는 선언 위치와 static 여부에 따라 4가지로 나누어져요!

종류 선언 위치 static 특징
인스턴스 내부 클래스 클래스 멤버 위치 X 가장 일반적
정적 내부 클래스 클래스 멤버 위치 O 외부 인스턴스 불필요
지역 클래스 메서드 안 X 잘 사용하지 않음
익명 클래스 메서드 안 X 이름 없음, 1회용

2. 인스턴스 내부 클래스

외부 클래스의 멤버 위치에 선언하는 가장 일반적인 내부 클래스.

외부 클래스의 모든 멤버(private 포함)에 접근할 수 있습니다.

public class Car {
    private String model;
    private int speed;

    public Car(String model) {
        this.model = model;
        this.speed = 0;
    }

    // 인스턴스 내부 클래스
    class Engine {
        private int rpm;

        Engine(int rpm) {
            this.rpm = rpm;
        }

        void start() {
            // 외부 클래스의 private 필드에 직접 접근 가능
            System.out.println(model + " 엔진 시동 — rpm: " + rpm);
            speed = 100;  // 외부 클래스 필드 수정도 가능
        }

        void showCarInfo() {
            // 외부 클래스 이름.this 로 외부 인스턴스 명시적 참조
            System.out.println("차량 모델: " + Car.this.model);
        }
    }

    public void drive() {
        Engine engine = new Engine(3000);
        engine.start();
    }
}
// 사용법
Car car = new Car("소나타");

// 방법 1 — 외부 클래스 메서드를 통해 사용 (일반적)
car.drive();  // 소나타 엔진 시동 — rpm: 3000

// 방법 2 — 외부에서 직접 생성
Car.Engine engine = car.new Engine(5000);
engine.start();  // 소나타 엔진 시동 — rpm: 5000

핵심 포인트

  • 인스턴스 내부 클래스 객체를 만들려면 외부 클래스 객체가 먼저 있어야 해요.
  • 외부에서 직접 생성할 때는 외부객체.new 내부클래스() 문법을 써요.
  • 내부 클래스 안에서 외부 클래스 인스턴스를 참조할 때는 외부클래스.this를 써요.

3. 정적 내부 클래스(Static Nested Class)

static 키워드를 붙인 내부 클래스입니다.

외부 클래스의 인스턴스 없이도 사용할 수 있어요. 단, 외부 클래스의 인스턴스 멤버에는 접근할 수 없고 static 멤버에만 접근할 수 있죠.

public class MathUtil {
    private static final double PI = 3.14159;

    // 정적 내부 클래스
    static class Circle {
        private double radius;

        Circle(double radius) {
            this.radius = radius;
        }

        double area() {
            return PI * radius * radius;  // 외부 클래스의 static 필드 접근 가능
        }

        double circumference() {
            return 2 * PI * radius;
        }
    }

    static class Rectangle {
        private double width, height;

        Rectangle(double width, double height) {
            this.width  = width;
            this.height = height;
        }

        double area() {
            return width * height;
        }
    }
}
// 외부 클래스 인스턴스 없이 바로 생성 가능
MathUtil.Circle circle = new MathUtil.Circle(5.0);
System.out.println("넓이: " + circle.area());          // 넓이: 78.53975
System.out.println("둘레: " + circle.circumference()); // 둘레: 31.4159

MathUtil.Rectangle rect = new MathUtil.Rectangle(4.0, 6.0);
System.out.println("넓이: " + rect.area());  // 넓이: 24.0

4. 지역 클래스(Local Class)

메서드 안에 선언하는 클래스.

잘 사용하지 않았습니다. 저도 이런게 있구나 정도로만 공부했어요 ㅎ

public class Printer {

    void printMessage(String message) {

        // 메서드 안에 클래스 선언
        class Formatter {
            String format(String text) {
                return "[" + text.toUpperCase() + "]";
            }
        }

        Formatter formatter = new Formatter();
        System.out.println(formatter.format(message));
    }
}
Printer printer = new Printer();
printer.printMessage("hello");  // [HELLO]

5. 익명 클래스(Anonymous Class)

이름 없이 선언과 동시에 객체를 생성하는 클래스.

주로 인터페이스나 추상 클래스를 일회성으로 구현할 때 사용합니다.

람다 표현식으로 대체되는 경우가 많지만, 아직도 종종 볼 수 있는 것 같습니다.

// 인터페이스 정의
interface Greeting {
    void greet(String name);
}

// 방법 1 — 일반적인 구현 클래스
class KoreanGreeting implements Greeting {
    @Override
    public void greet(String name) {
        System.out.println("안녕하세요, " + name + "님!");
    }
}

Greeting g = new KoreanGreeting();
g.greet("홍길동");
// 방법 2 — 익명 클래스 (이름 없이 바로 구현)
Greeting g = new Greeting() {
    @Override
    public void greet(String name) {
        System.out.println("안녕하세요, " + name + "님!");
    }
};

g.greet("홍길동");  // 안녕하세요, 홍길동님!

new Greeting() {...} 에서 Greeting은 인터페이스임에도 new를 쓸 수 있습니다.

이 때 { } 안에 구현 코드를 바로 작성할 수 있어요.


6. 익명 클래스 → 람다 표현식

Java 8 부터는 함수형 인터페이스(추상 메서드가 1개인 인터페이스)를 구현할 때 익명 클래스 대신 람다 표현식으로 간결하게 쓸 수 있습니다.

// 함수형 인터페이스
interface Calculator {
    int calc(int a, int b);
}

// 익명 클래스 방식
Calculator add = new Calculator() {
    @Override
    public int calc(int a, int b) {
        return a + b;
    }
};

// 람다 표현식 방식 — 동일한 결과, 훨씬 간결
Calculator add = (a, b) -> a + b;

System.out.println(add.calc(3, 5));  // 8

'Language > Java' 카테고리의 다른 글

[Java] 예외 처리 (Exception Handling)  (0) 2026.04.23
[Java] String 파헤치기  (0) 2026.04.23
[Java] 배열에 대해서  (0) 2026.04.22
[Java] 추상 클래스 & 인터페이스 완전히 정리해버리기  (0) 2026.04.22
[Java] 상속 완전히 정리해버리기  (0) 2026.04.22
'Language/Java' 카테고리의 다른 글
  • [Java] 예외 처리 (Exception Handling)
  • [Java] String 파헤치기
  • [Java] 배열에 대해서
  • [Java] 추상 클래스 & 인터페이스 완전히 정리해버리기
BackendInho
BackendInho
항상 열정적으로 부딪히고 깨닫는 주니어 백엔드 개발자의 여정을 기록합니다!
  • BackendInho
    Inho.devlog
    BackendInho
  • 전체
    오늘
    어제
    • 분류 전체보기 (41)
      • TIL (0)
      • Language (21)
        • Java (21)
      • Backend (8)
        • Spring (8)
      • Database (0)
        • SQL (0)
      • CS (8)
        • Computer Structure (2)
        • Network (2)
        • OS (1)
        • Data Structure & Algorithms (3)
      • Devops (0)
        • Docker & Kubernetes (0)
      • Coding-Test (1)
        • Programmers (3)
        • LeatCode (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    API
    CS
    HTTP
    java
    REST
    REST API
    Spring
    Spring Boot
    Web
    공간복잡도
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
BackendInho
[Java]내부 클래스 정리
상단으로

티스토리툴바