[Java] 심화 - 내부클래스(Inner Class), 익명클래스(Anonymous Class), 람다식(Lambda)

이지연·2025년 12월 20일

개요

아래의 내용은 java_grammer 레파지토리 C05AnonymousLambda 디렉터리에 저장되어있는 내용을 정리함


1. 내부클래스 (Inner Class)

내부클래스란, 클래스 안에 정의된 또 다른 클래스를 의미함.
코드 구조를 조직화하거나 외부 클래스와 긴밀한 관계를 표현할 때 사용되는 것임.

주요 종류는 아래와 같음.

종류설명
static 내부클래스바깥 클래스의 인스턴스 없이 독립적으로 사용할 수 있음. (static 변수처럼 작동함)
비static 내부클래스바깥 클래스의 인스턴스가 있어야 생성할 수 있음. (이번 예제엔 없음)
익명 내부클래스(anonymous)이름 없는 내부 클래스 (다음 섹션에서 따로 설명)

static 내부클래스 예시

package C05AnonymousLambda;

public class C01InnerClass {
    public static void main(String[] args) {
        // static 내부클래스의 객체 생성
        Member.MemberInner m1 = new Member.MemberInner(20);
        System.out.println(m1.getB());
    }
}

class Member {
    private int a;

    public int getA() {
        return this.a;
    }

    public Member(int a) {
        this.a = a;
    }

    // static 내부클래스 정의
    static class MemberInner {
        private int b;

        public int getB() {
            return b;
        }

        public MemberInner(int b) {
            this.b = b;
        }
    }
}

코드 설명

Member 클래스 안에 static class MemberInner를 선언한 구조임.
Member.MemberInner m1 = new Member.MemberInner(20); ← 이렇게 바깥 클래스 이름을 통해 바로 접근 가능함.
MemberInnerMember의 인스턴스를 생성하지 않아도 독립적으로 사용할 수 있는 구조임.

즉, static 내부클래스는 바깥 클래스의 멤버처럼 취급되며, 외부 인스턴스 없이 동작 가능한 것임.


2. 익명 내부클래스 (Anonymous Inner Class)

익명 내부클래스는 이름이 없는 클래스로,
인터페이스나 추상클래스를 즉시 구현하기 위한 임시 클래스를 생성하면서 동시에 객체를 만드는 방식임.

일반적으로 인터페이스나 추상클래스를 상속받는 구현체 클래스가 별도로 존재하지 않을 때 사용함.


익명 내부클래스 예시

package C05AnonymousLambda;

public class C02AnonymousClass {
    public static void main(String[] args) {

        // 추상클래스를 이용한 익명 객체 생성
        AbstractAnimal aa = new AbstractAnimal() {
            @Override
            void makeSound() {
                System.out.println("멍멍");
            }
        };

        aa.makeSound();
        aa.eat();

        // 인터페이스로도 가능
        Animal1 a1 = new Animal1() {
            @Override
            public void makeSound() {
                System.out.println("인터페이스 소리지롱");
            }

            @Override
            public void eat() {
                System.out.println("인터페이스 냠냠");
            }
        };
    }
}

핵심 정리

new AbstractAnimal() { ... }
→ 여기서 중괄호 {} 안에 정의된 내용이 즉시 구현된 익명 클래스로 컴파일됨.
즉, 별도의 클래스를 정의하지 않고 즉석에서 상속 및 메서드 구현을 수행하는 것임.
Animal1, AbstractAnimal처럼 구현체가 없는 타입(인터페이스/추상클래스)에 주로 사용함.


3. 람다식(Lambda Expression)

람다식은 익명 내부클래스의 축약형 표현으로,
함수형 인터페이스(= 메서드를 하나만 가지는 인터페이스)에 사용할 수 있는 문법임.

형태:
(매개변수) → { 실행문 }

익명 내부클래스를 간결하게 줄임.
코드가 짧고 가독성이 높아짐.
함수형 프로그래밍 스타일을 지원하는 문법적 핵심 기능임.


기본 예시

interface Animal2 {
    void makeSound();
}

public class C02AnonymousClass {
    public static void main(String[] args) {
        // 람다 예시 1: 여러 줄 실행
        Animal2 a2_1 = () -> {
            System.out.println("hello world1");
            System.out.println("hello world2");
        };
        a2_1.makeSound();

        // 람다 예시 2: 실행문 한 줄이면 중괄호 생략 가능
        Animal2 a2_2 = () -> System.out.println("hello world1");
        a2_2.makeSound();
    }
}

정리

인터페이스 내 메서드가 하나만 있는 경우 (@FunctionalInterface) 람다식 사용 가능.
a2_1은 다중라인, a2_2는 단일라인 람다 표현식임.


4. 매개변수와 리턴이 있는 람다식

람다는 단순 출력뿐만 아니라, 매개변수를 받아 계산 후 리턴할 수도 있음.

interface Animal3 {
    String makeSound(String a, String b, String c);
}

public class C02AnonymousClass {
    public static void main(String[] args) {
        // 기본 형태
        Animal3 a3_1 = (a, b, c) -> {
            return a + "," + b + "," + c;
        };
        System.out.println(a3_1.makeSound("java", "c", "node"));

        // 한 줄 실행 시 `return` 생략 가능
        Animal3 a3_2 = (a, b, c) -> a + "," + b + "," + c;
    }
}

매개변수가 여러 개인 경우 괄호로 묶고, 리턴값이 있을 땐 return 혹은 단일 표현식 형태 모두 가능함.


실습 예제 – 조건 분기 포함 람다

interface Animal4 {
    String makeSound(int n, String a, String b);
}

public class C02AnonymousClass {
    public static void main(String[] args) {
        Animal4 a4 = (n, a, b) -> {
            if (n >= 10) {
                return a + b;
            } else {
                return a;
            }
        };
        System.out.println(a4.makeSound(8, "강아지", "고양이"));
        System.out.println(a4.makeSound(12, "강아지", "고양이"));
    }
}

출력 결과는 다음과 같음.

강아지
강아지고양이

입력받은 숫자 n이 10 이상이면 두 문자열을 결합,
그 미만이면 첫 문자열만 반환하는 형태임.


전체 흐름 정리

개념주요 키워드설명
내부 클래스 (Inner Class)static, MemberInner클래스 내부에 선언된 서브 클래스. 외부 데이터와 밀접한 관계 표현용.
익명 내부 클래스 (Anonymous Class)new Interface() {}별도 클래스 정의 없이 즉시 구현 및 객체 생성.
람다식 (Lambda Expression)(매개변수) -> { 실행문 }익명 내부클래스의 축약 표현. 함수형 인터페이스와 함께 사용.

요약 정리

내부클래스 → 클래스 안에 정의된 클래스. 코드 조직화 및 정보 은닉에 유용함.
익명 내부클래스 → 이름 없는 구현 클래스. 인터페이스나 추상클래스를 즉석에서 구현할 때 사용함.
람다식 → 익명 클래스의 한 줄 표현식. 함수형 인터페이스에 최적화되어 있음.
코드 간결성, 유지보수성, 이벤트 핸들링 등에서 자주 쓰이는 문법임.

profile
Eazy하게

0개의 댓글