람다식

현서·2025년 5월 29일
1

자바

목록 보기
19/32
post-thumbnail

1. 익명 객체(anonymous object)

  • 이름이 없는 클래스를 정의하고 그 객체를 한 번만 사용하고자 할 때 사용하는 기법.
  • 인터페이스나 추상 클래스를 구현/상속하면서 동시에 객체로 생성할 때 사용된다.
    -> 객체를 표현하기 위한 별도 클래스의 이름 없이 직접 정의하고 생성함.
package lesson07;

abstract class Ex10_Animal {
    public abstract void speak();
}

public class Ex10_Main {
    public static void main(String[] args) {
        // 익명 객체 생성
        // 클래스 이름 없이 바로 구현 및 인스턴스 생성
        Ex10_Animal tiger = new Ex10_Animal() {
            @Override
            public void speak() {
                System.out.println("어흥! 나는 호랑이야!");
            }
        };

        Ex10_Animal dog = new Ex10_Animal() {
            @Override
            public void speak() {
                System.out.println("멍멍! 나는 강아지야!");
            }
        };

        tiger.speak();
        dog.speak();
    }
}
  • Animal이라는 추상 클래스를 구현하는 이름 없는 클래스를 만들어서 곧바로 객체 생성
  • 메서드 오버라이딩 바로 가능
package lesson07;

interface Ex11_ButtonClickListener{
    void onClick();
}

public class Ex11_Main {
    public static void main(String[] args) {
        Ex11_ButtonClickListener listener = new Ex11_ButtonClickListener() {
            @Override
            public void onClick() {
                System.out.println("버튼이 클릭되었습니다.");
            }
        };
        listener.onClick();
    }
}

2. 람다(Lambda)

  • 익명 함수를 간결하게 표현하는 문법.
  • 보통 함수형 인터페이스를 구현할 때 사용된다.
  • 메서드를 하나만 갖는 인터페이스의 구현을 코드 블록 없이 매개변수 -> 실행문 형식으로 간단히 작성할 수 있도록 해준다.
(매개변수) -> { 실행문 }
  • 매개변수가 1개이면 괄호 () 생략 가능
  • 실행문이 한 줄이면 {}와 return 생략 가능

함수형 인터페이스(Functional Interface)

  • 오직 하나의 추상 메서드만 가지는 인터페이스.
  • 별도의 클래스 없이 람다로 간단히 구현할 수 있어 코드가 간결해진다.
  • @FunctionalInterface 어노테이션을 사용하면 컴파일러가 해당 인터페이스가 함수형 인터페이스임을 검증해주며, 실수로 두 개 이상의 추상 메서드를 선언했을 때 오류를 발생시켜준다.
  • ex) Runnable, Callable, Comparator, Consumer 등
@FunctionalInterface
interface MyPrinter {
    void print(String message);
}

※ 함수형 인터페이스에는 @FunctionalInterface 어노테이션을 붙이는 것이 관례.

1. 매개변수 없음, 반환값 없음

@FunctionalInterface
interface Hello {
    void sayHello();
}

public class Main {
    public static void main(String[] args) {
        Hello h = () -> System.out.println("안녕하세요!");
        h.sayHello();
    }
}

2. 매개변수 있음, 반환값 없음

@FunctionalInterface
interface Printer {
    void print(String message);
}

public class Main {
    public static void main(String[] args) {
        Printer p = msg -> System.out.println("출력: " + msg);
        p.print("람다 표현식!");
    }
}

3. 매개변수 여러 개, 반환값 있음

@FunctionalInterface
interface Adder {
    int add(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        Adder adder = (a, b) -> a + b;
        System.out.println("합계: " + adder.add(5, 7)); // 12
    }
}

4. 실행문 여러 줄 (중괄호 {}와 return 사용)

@FunctionalInterface
interface Comparator {
    int compare(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        Comparator comp = (a, b) -> {
            System.out.println("비교 중...");
            return Integer.compare(a, b);
        };

        System.out.println("결과: " + comp.compare(10, 20)); // -1
    }
}

5. 람다식과 컬렉션 API

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("사과", "바나나", "오렌지");

        // forEach에 람다 적용
        fruits.forEach(fruit -> System.out.println("과일: " + fruit));
    }
}

랜덤 퀴즈 게임

package lesson07;

import java.util.*;

@FunctionalInterface
interface Checker{
    boolean check(String userAnswer, String correctAnswer);
}

public class Ex12_Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        Map<String, String> questionMap = new LinkedHashMap<>();
        questionMap.put("자바에서 문자열을 나타내는 클래스는?", "String");
        questionMap.put("자바에서 반복문을 사용하는 키워드는?", "for");
        questionMap.put("자바에서 클래스를 정의할 때 사용하는 키워드는?", "class");
        questionMap.put("자바에서 상속을 표현하는 키워드는?", "extends");
        questionMap.put("자바의 논리 연산자 중 하나는?", "&&");

        List<Map.Entry<String, String>> entries = new ArrayList<>(questionMap.entrySet());
        Collections.shuffle(entries);

        Checker checker = (user, correct) -> user.trim().equalsIgnoreCase(correct);
        // equalsIgnoreCase: 대소문자 무시하고 구별
        System.out.println("퀴즈 게임 시작");
        int score = 0;
        for(Map.Entry<String, String> entry: entries){
            String question = entry.getKey();
            String answer = entry.getValue();
            System.out.println("문제: " + question);
            System.out.print("당신의 답변: ");
            String userInput = sc.nextLine();

            if(checker.check(userInput, answer)){
                System.out.println("정답!");
                score++;
            }else{
                System.out.println("오답! 정답은 [" + answer + "]입니다.");
            }
        }
        System.out.println("게임 종료! 당신의 점수는 " + score + "점입니다.");
        sc.close();
    }
}
profile
The light shines in the darkness.

0개의 댓글