Java / / 2024. 7. 4. 17:01

Nested Classes, Local Classes, Anonymous Classes, and Lambda Expressions

자바에서는 코드를 더 모듈화하고 재사용 가능한 방식으로 작성할 수 있도록 다양한 유형의 클래스를 제공합니다. 이번 글에서는 중첩 클래스, 로컬 클래스, 익명 클래스, 람다 표현식을 깔끔하게 정리해보겠습니다. 각 클래스 유형의 개념과 사용 사례를 알아보겠습니다. 🚀

 

1. 🏗️ 중첩 클래스 (Nested Class)

 

중첩 클래스는 외부 클래스 내부에 정의된 클래스로, 외부 클래스와 밀접한 관계를 가집니다. 중첩 클래스는 **정적 중첩 클래스(Static Nested Class)**와 **내부 클래스(Inner Class)**로 나뉩니다.

 

1.1 정적 중첩 클래스 (Static Nested Class)

 

static 키워드로 정의된 클래스입니다.

외부 클래스의 인스턴스 없이 생성할 수 있습니다.

외부 클래스의 정적 멤버에만 접근할 수 있습니다.

class Outer {
    static class Inner {
        void display() {
            System.out.println("Static Nested Class");
        }
    }
}

 

1.2 내부 클래스 (Inner Class)

 

static 키워드 없이 정의된 클래스입니다.

외부 클래스의 인스턴스가 있어야 생성할 수 있습니다.

외부 클래스의 모든 멤버(정적 및 비정적)에 접근할 수 있습니다.

class Outer {
    private String message = "Hello, World!";
    
    class Inner {
        void display() {
            System.out.println(message);
        }
    }
    
    void showMessage() {
        Inner inner = new Inner();
        inner.display();
    }
}

 

2. 📍 로컬 클래스 (Local Class)

 

로컬 클래스는 메서드, 생성자 또는 초기화 블록 내부에 정의된 클래스로, 해당 블록 내에서만 사용될 수 있습니다.

 

외부 클래스의 인스턴스 멤버와 메서드의 로컬 변수(암묵적 final)에 접근할 수 있습니다.

public class Test {
    public void sortNumbers() {
        class IntegerComparator implements Comparator<Integer> {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        }
        
        List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);
        Collections.sort(list, new IntegerComparator());
    }
}

 

3. 🔍 익명 클래스 (Anonymous Class)

 

익명 클래스는 이름이 없는 클래스로, 주로 인터페이스나 추상 클래스를 구현할 때 사용됩니다. 정의와 동시에 인스턴스를 생성할 수 있습니다.

 

한 번만 사용할 수 있는 일회용 클래스입니다.

public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Anonymous Inner Class Runnable");
            }
        };
        
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

 

4. ⚡ 람다 표현식 (Lambda Expression)

 

람다 표현식은 자바 8부터 도입된 기능으로, 함수형 인터페이스를 구현할 때 사용됩니다. 코드가 간결해지고, 명확한 함수형 프로그래밍 스타일을 사용할 수 있습니다.

public class Test {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);
        Collections.sort(list, (o1, o2) -> o1 - o2);
        
        list.forEach(num -> System.out.print(num + " "));
    }
}

 

5. 🔒 정적 초기화 블록 (Static Initialization Block)

 

정적 초기화 블록은 클래스가 처음 로드될 때 실행되는 코드 블록입니다. 주로 클래스 레벨에서 한 번만 실행되어야 하는 초기화 작업을 수행할 때 사용됩니다.

class Test {
    static int data;
    
    static {
        data = 30;
        System.out.println("Static Initialization Block");
    }
}

 

📝 Quiz Time! 📝

 

1. 문제 1

Q: 다음 코드의 출력 결과는 무엇입니까?

class Outer {
    private String message = "Hello, World!";    
    class Inner {
        void display() {
            System.out.println(message);
        }
    }    
    void showMessage() {
        Inner inner = new Inner();
        inner.display();
    }
}

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.showMessage();
    }
}

 

A: Hello, World!

 

2. 문제 2

Q: 다음 코드의 컴파일 결과는 어떻게 됩니까?

class Outer {
    private int data = 30;    
    static class Inner {
        void display() {
            // System.out.println(data);  // 이 줄은 컴파일 오류가 발생합니다.
        }
    }    
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.display();
    }
}

 

A: 컴파일 오류가 발생합니다.

이유: data는 인스턴스 변수이므로 정적 중첩 클래스에서는 접근할 수 없습니다.

 

3. 문제 3

Q: 익명 내부 클래스를 사용하여 Runnable 인터페이스를 구현하세요.

public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Anonymous Inner Class Runnable");
            }
        };
        
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

 

4. 문제 4

Q: 다음 중 내부 클래스의 장점으로 올바르지 않은 것은 무엇입니까?

 

A. 캡슐화를 더 강화할 수 있다.

B. 외부 클래스의 모든 멤버에 접근할 수 있다.

C. 코드의 복잡성을 줄인다.

D. 상속 관계를 통해 클래스 간 결합도를 낮춘다.

 

A: D. 상속 관계를 통해 클래스 간 결합도를 낮춘다.

 

5. 문제 5

Q: **지역 내부 클래스(Local Inner Class)**에 대해 설명하고, 다음 메소드 안에 지역 내부 클래스를 사용하여 Comparator<Integer>를 구현하세요.

import java.util.*;

public class Test {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        
        for (int num : list) {
            System.out.print(num + " ");
        }
    }
}

 

📚 마무리

 

이 글이 자바의 다양한 클래스 사용에 대한 이해를 돕는 데 도움이 되기를 바랍니다. 필요한 경우 각 개념을 상황에 맞게 활용하여 더욱 효율적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다. ✨

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유