JAVA

[JAVA] 람다 표현식을 사용하는 함수형 인터페이스

정공자씨 2024. 5. 2. 12:21

 

 

 

람다 표현식 사용하기 : 함수형 인터페이스

아무런 클래스의 메서드나 추상 클래스의 메서드를 람다 표현식으로 줄일 수 있는 것이 아니고, 함수형 인터페이스만 람다식으로 표현이 가능함

[ 함수형 인터페이스 ]
- 1개의 추상메서드를 가진 인터페이스
- 인터페이스에 정의된 하나의 추상 메서드는, 함수형 인터페이스의 구현체인 람다 표현식을 실행시키는 메서드
- 즉, 람다식으로 표현이 가능한 인터페이스를 가리켜서 함수형 인터페이스

 

 

함수형 인터페이스

개념

  • 함수형 인터페이스는 딱 1개의 추상 메서드만 선언되어 있는 인터페이스
  • 람다식은 함수형 인터페이스 안에 정의된 1개의 추상 메서드의 구현 부분을 짧게 표현한 것
  • 즉, 람다식으로 구현하는 메서드 인터페이스의 추상메서드여야 함

 

[ 함수형 인터페이스 ]

// 함수형 인터페이스 : 추상 메서드가 1개
interface InterA {
    int add(int x, int y);
}
// 함수형 인터페이스 X : 추상 메서드가 2개
interface InterB {
    int add(int x, int y);
    int min(int x, int y);
}

 

 

함수형 인터페이스 선언

interface MyInterface{
    public abstract int method(int a);
}
  • 메서드의 반환타입, 매개변수의 개수, 매개변수 타입을 확인할 것!
  • 위의 함수형 인터페이스를 보고 알 수 있는 것은
    • 반환 값이 int이고, int형의 매개변수를 1개를 받는 메서드를 람다식으로 만든다는 뜻

 

 

@FunctionalInterface 사용하기

1. 개념

  • @FunctionalInterface로 지정하면
  • 인터페이스에 추상 메서드가 1개만 선언되었는지를 컴파일러가 체크할 수 있음
  • 즉 해당 어노테이션을 인터페이스 선언부에 붙이면, 컴파일러가 해당 인터페이스를 함수형 인터페이스로 인식
    • 이렇게 명시된 함수형 인터페이스에 2개 이상의 메서드가 선언되면 오류를 발생시킴

2. 에러 발생 확인

 

3. 형식

@FunctionalInterface
interface MyInterface {  // 함수형 인터페이스
    public abstract void methodA();  // 추상메서드가 2개 이상이면 컴파일러 발생
}
// 인터페이스명  변수  = 람다식
MyInterface mi = () → {
	System.out.println("추상메서드를 람다식으로 구현")
}

// 메서드 호출
mi.methodA();

 

 

 

함수형 인터페이스 : 람다 표현식을 하나의 변수에 대입할 때 사용하는 참조변수의 타입

  • 람다 표현식을 사용할 때는, 람다 표현식을 저장하기 위한 참조변수 타입을 결정해야 하는데
  • 람다 표현식을 하나의 변수에 대입할 때 사용하는, 참조변수의 타입을 함수형 인터페이스라고 함
인터페이스명 참조변수 = 람다 표현식

 

 

함수형 인터페이스를 선언하고, 추상메서드를 람다식으로 표현하기

interface IFruit {
	public String eat();
}
public class Main {
    public static void main(String[] args) {
    
    	// 인터페이스명 변수 = 람다식
    	IFruit fruit = () -> {
        	return "과일을 먹습니다";
        }    	
        fruit.eat();
        
        
        // 인터페이스명 변수 = new 인터페이스명() {}
        IFruit fruit2 = new IFruit () {        
                @Override
                public String eat() {
                     return "과일을 먹습니다";
                }    	
        }
        fruit2.eat();        
    }
}
람다식으로 구현된 메서드를 보면 메서드를 변수로 선언하는 것처럼 보이지만, 실제로 자바에서는 메서드를 단독으로 선언할 수 없음
  • 람다 표현식을 함수형 인터페이스타입 변수에 대입하고, 변수를 통해 메서드를 호출하여 사용하는 것
    • 참조변수를 통해 메서드를 호출하여 사용하는 모습은, 마치 객체와 다름이 없음
  • 즉, 람다식도 결국은 객체이고
  • 인터페이스 익명 구현 객체를 짧게 표현하여 사용
    • 그렇다고 익명 클래스와 람다 표현식이 같은 것은 아님

 

인터페이스 익명 구현 객체 
1. 익명 클래스를 주로 사용하는 곳은, 인터페이스를 익명 클래스로 구현하여 사용할 때임
2. 원래는 클래스가 인터페이스를 구현하고, 인터페이스를 구현한 클래스의 객체를 생성한 후에, 메서드를 사용할 수 있는데
3. 익명 클래스를 이용하여 인터페이스를 구현하는 클래스를 별도로 생성하지 않고, 인터페이스를 바로 구현하여서 객체를 만들기 때문에 인터페이스 익명 구현 객체(익명으로 인터페이스를 구현한 객체)라고 함
4. 익명 클래스는 일회성으로 사용하는 메서드를 구현하기 위해서 주로 사용하는데, 추상화 구조인 인터페이스를 일회용으로 구현하여 사용할 필요가 있을 때 익명 구현 객체로 선언하여 이용하면 좋음

interface IFruit {
    public String eat();  // 추상메서드
    public String wash();
}​
public class Main {
    public static void main(String[] args) {
    
        // 인터페이스 익명 구현 객체
        // 인터페이스타입  변수 = new 인터페이스 타입 
        IFruit fruit = new IFruit() {
                @Override
                public String eat() {
                    return "과일을 먹습니다";
                }

                @Override
                public String wash() {
                    return "과일을 씻습니다";
                }
        };
        
        // 인터페이스 구현 객체 사용
        fruit.eat();
        fruit.wash();
    }
}

 

 

예제 

@FunctionalInterface
interface MyFunctInterface {	
        public void methodA();
        // public void methodB();  // 추상메서드 2개 이상이면 에러 발생	
}
public class Test {
    public static void main(String[] args) {
    
        // 1. 익명 클래스를 이용하여 추상메서드 구현
        MyFunctInterface mi1 = new MyFunctInterface() {			
            @Override
            public void methodA() {
                System.out.println("methodA() 호출");
            }
        };
        mi1.methodA();   // methodA() 호출
        
        // 1-1. 익명 클래스를 이용하여 추상메서드 구현
        new MyFunctInterface() {			
            @Override
            public void methodA() {
                System.out.println("methodA() 호출");
            }
        }.methodA();


        // 2. 람다식 표현: 매개변수와 리턴 타입이 없는 메서드
        MyFunctInterface mi2 = () -> {
            System.out.println("methodA() 호출");
        };
        mi2.methodA();  // methodA() 호출


        // 2-1. 실행문이 1줄인 경우, 중괄호 {} 생략 가능
        MyFunctInterface mi3 = () -> System.out.println("methodA() 호출");
        mi3.methodA();  // methodA() 호출
    }
}

 

 

 

 

함수형 인터페이스의 종류

  • java.util.function에는 자바의 빌트인 함수형 인터페이스가 40여개가 있음
  • 제공하는 함수형 인터페이스를 이용하여 프로그래밍할 수 있고
  • 필요한 경우 구현하여 사용할 수 있음
인터페이스명 추상 메소드 설명
Runnable void run() 기본적인 인터페이스, 매개변수와 반환값 없음
Supplier<T> T get() 매개변수 없음, 제네릭타입 반환값 가짐
Consumer<T> void accept() 제네릭 매개변수 하나, 반환값 없음(void)
Predicate<T> boolean test() 제네릭 매개변수 하나, Boolean 반환값 하나
Function<T,R> R apply(T t) 제네릭 매개변수 하나와 다른 제네릭 반환값하나
Comparator<T> int compare(T o1, T o2) 같은 제네릭 타입 매개변수 두개를 받고, Integer 반환값 하나 가짐,
객체간 비교를 위핸 compare를 위한 인터페이스
BiConsumer<T,U> void accept(T t, U u) 서로다른 제네릭 매개변수 두개를 받고 반환값 없음
BiFunction<T,U,R> R apply(T t, U u) 서로 다른 제네릭 매개변수 두개를 받고
다른 제네릭 타입의 반환값 하나
BiPridicate<T,U> boolean test(T t, U u) 서로 다른 제네릭 타입의 매개변수 2개를 받고
Boolean 타입의 반환값 하나 가짐

 

 

 

 

 

 

 

 

 

출처

 

 

람다식(feat. 익명 구현 클래스 vs 람다식)

선장님과 함께하는 마지막 자바 스터디입니다. (ㅜ) 자바 스터디 Github github.com/whiteship/live-study whiteship/live-study 온라인 스터디. Contribute to whiteship/live-study development by creating an account on GitHub. github.c

alkhwa-113.tistory.com

 

☕ 람다 표현식(Lambda Expression) 완벽 정리

람다 표현식 (Lambda Expression) 람다 표현식(lambda expression)이란 함수형 프로그래밍을 구성하기 위한 함수식이며, 간단히 말해 자바의 메소드를 간결한 함수 식으로 표현한 것이다. 지금까지 자바에

inpa.tistory.com

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 

자바의 람다식(Lambda) - 2. 람다식 사용하기

메소드를 람다식으로 변경하는 방법에 대해서는 이전 포스팅을 참고 해주시기 바랍니다. ☞ 자바의 람다식(Lambda) - 1. 람다식으로 표현하기 람다식 사용하기 - 함수형 인터페이스 람다식으로 바

siyoon210.tistory.com