ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JAVA 람다와 스트림 - 함수형 인터페이스
    개발언어/JAVA 2023. 12. 15. 16:50

    함수형 인터페이스

     

    ▶ 함수형 인터페이스 - 단 하나의 추상 메서드만 선언된 인터페이스 

    @FunctionalInterface
    interface MyFunction{
        public abstract int max(int a, int b);
    }

     

    인터페이스의 모든 메서드는 public이면서 abctract하기 때문에 2가지 키워드는 생략 가능하다. 

     

    💡 tip)  오버라이딩(Overriding)제어자

    오버라이딩은 할 때 오버라이딩 하는 메서드의 접근 제어자는 넓은 범위에서 좁은 범위로 바꿀 수 없다. 즉 인터페이스에서 public 접근제어자 메서드를 오버라이딩 하여 구현하면 default, private으로 바꿀 수 없다.

     

     

    MyFunction 구현

    MyFunction f = new MyFuction(){
                    public int max(int a, int b){
                            return a > b > a : b;
                      }
    		};

     

    위 코드는 익명 클래스의 클래스 선언과 객체 생성을 동시에 한 것이다. 

     

     

    익명 객체의 메서드 사용

    int value = f.max(3,5); // OK. MyFunction에 max()가 있다.

     

    함수형 인터페이스를 사용해서 Object 타입대신에 사용하는 것이다. 

     

     

    ▶ 함수형 인터페이스 타입의 참조변수로 람다식을 참조할 수 있다.

    단, 함수형 인터페이스의 메서드와 람다식의 매개변수 개수반환타입일치해야 한다.

    그리고 함수형 인터페이스는 단 하나의 추상 메서드만 가져야 한다.

    //람다식(익명객체)을 다루기 위한 참조변수의 타입은 함수형 인터페이스로 한다. 
    MyFunction f = (a, b) -> a > b ? a : b;
    int value = f.max(3,5) //실제로는 람다식(익명 함수)이 호출된다.

     

    람다식을 대입할 참조변수를 타입을 미리 선언한 함수형 인터페이스로 사용하면 된다. 함수형 인터페이스는 람다식을 다루기 위해 존재 한다. 

     

    람다식을 다룰려면 람다식이 익명 객체이기 때문에 참조변수 타입이 되어출 함수인터페이스가 필요하다. 덧붙이자면 람다식은 익명 객체의 익명함수이다. 그래서 람다식을 사용할 때는 함수형 인터페이스에 선언된 메서드 이름을 사용한다. 

     

     

    람다식의 사용 

     

    결국 람다식이라는 것은 메서드 이고, 이 메서드를 만든 목적은 사용하기 위함이다. 이를 위해서는 람다식에 이름이 있어야 한다. 다시 말해 람다식 자체는 익명 함수로 이름을 없앴지만 이것을 사용하려면 이름이 필요하다. 그래서 함수형 인터페이스에 정의된 매서드의 이름이 람다식을 사용할 때 호출을 위해 사용된다. 

     


    함수형 인터페이스 - example

    ▶ 익명 객체를 람다식으로 대체

     

    Comparator.java(java.util)

    @FuntionalInterface
    public interface Comparator<T>{
        int compare(T o1, T o2);
        ...
    }

     

    Comparator 함수 인스턴스는 compare()이라는 추상 메서드 하나만 가지고 있다. 

     

     

    익명 객체 인스턴스로 Comparator 선언과 생성

    List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");
    
    Collections.sort(list, new  Comparator<String>(){
    		public int compare(String s1, String s2){
            		return s2.compareTo(s1);
            }
    });

     

     

    람다식(익명 함수)로 Comparator 선언과 생성

    List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");
    Collections.sort(list, (s1,s2) -> s2.compareTo(s1));

     

    Collection.sort()메서드는 List<String>형의 인스턴스와 Comparator<T>형의 인스턴스를 파라미터로 받는다. 


    함수형 인터페이스 타입의 매개변수, 반환타입

     

    ▶함수형 인터페이스 타입의 매개변수

    MyFunction.java

    @FunctionalInterface
    interface MyFunction{
       void myMethod();
    }
    void aMethod(MyFunction f){	
        f.myMethod(); // MyFunction에 정의된 메서드 호출
    }

     

    위 코드는 메서드의 매개변수로 함수형 인터페이스를 받는다.메서드의 매개변수로 람다식을 받는다는 의미이다. 그리고 람다식을 매개변수로 받은 메서드에서는 람다식을 호출한다. 또한 함수형 인터페이스는 람다식의 이름을 붙여주고 그것을 호출 할 수 있게 해준다. 

     

    aMethod를 호출하는 코드

    public class Example3 {
        void aMethod(MyFuntion f){
            f.myMethod();
        }
    
        public static void main(String[] args) {
       		 //방법1
             MyFuntion f = () ->  System.out.println("myMethod()"); 
             new Example.aMethod(f;)
            
            //방법2
            new Example3().aMethod(() -> System.out.println("myMethod()"));
        }
    }

     


     

    ▶함수형 인터페이스 타입의 반환타입

    MyFunction myMethod(){
       MyFuntion f = () ->{};
        return f;
    }

     

    위 코드의 메서드 myMethod()는 반환값으로 MyFunction형의 람다식(함수형인터페이스의 메서드)를 가진다.

     

    MyFunction myMethod(){
        return () ->{};
    }

    위 코드의 메서드는 람다식(함수형 인터페이스 타입)을 반환하는 메서드가 된다.

     


    정리 예제 코드

    package lambda;
    
    @FunctionalInterface
    public interface MyFunction4 {
        public abstract void run();
    }
    
    public class Example4 {
        static void execute(MyFunction4 f){
            f.run();
        }
    
        static MyFunction4 getMyFunction(){
            //MyFunction4 f = () -> System.out.println("f3.run()");
            return  () -> System.out.println("f3.run()");
        }
        public static void main(String[] args) {
            //람다식으로 Myfunction4의 run()을 구현, 생성
            MyFunction4 f1 = () -> System.out.println("f1.run()");
    
            //익명 클래스로 run을 구현, 생성
            MyFunction4 f2 = new MyFunction4() {
                @Override
                public void run() {
                    System.out.println("f2.run()");
                }
            };
    
            MyFunction4 f3 = getMyFunction();
    
            f1.run(); //람다식으로 함수형 인터페이스 형으로 구현
            f2.run(); //익명함수로 구현
            f3.run(); //람다식을 결과 값으로 반환하는 메서드로 구현
            execute(() -> System.out.println("run()") ); //매개변수 값으로 람다식 전달
    
        }
    }

     

     

    [출처 - 자바의 정석 - 기초편 , 저 남궁성]

    https://www.youtube.com/watch?v=0Sp9eFRV8gE

    댓글

Designed by Tistory.