본문 바로가기
JAVA

람다식

by e-pd 2021. 3. 5.

https://github.com/whiteship/live-study/issues/15

학습주제

  • 람다식 사용법
  • 함수형 인터페이스
  • Variable Capture
  • 메소드, 생성자 레퍼런스

 

람다식 사용법

함수형 인터페이스를 통해 익명 내부 클래스 구현을 람다식으로 구현할 수 있다.

 

 

실행문이 한줄인 경우 
(매개변수..) -> 실행문

실행문이 여러 줄인 경우
(매개변수..) -> {
  실행문1, 
  실행문2
};

 

매개변수와 실행문 사이에 화살표 연산자 -> 를 넣어서 구분. 매개변수가 한개면 괄호를 생략 가능하다.

 

public class Main {
    public static void main(String[] args) {
    
        PrintAge func = (v) -> System.out.printf("나이는 %d 살입니다.", v);
        func.print(8); // 나이는 8 살입니다.
    }
}

@FunctionalInterface
interface PrintAge {
    void print(int age);
}

 

다시 익명 내부 클래스로 변경하면 다음과 같다.

 

public class Main {
    public static void main(String[] args) {
   
        PrintAge func = new PrintAge() {
            @Override
            public void print(int age) {
                System.out.printf("나이는 %d 살입니다.", age);
            }
        };
        func.print(8); // 나이는 8 살입니다.
    }
}

@FunctionalInterface
interface PrintAge {
    void print(int age);
}

 

함수형 인터페이스

  • Java8 부터 제공
  • 단 한 개의 추상 메서드를 갖고 있는 인터페이스
  • @FunctionalInterface를 붙여 함수형 인터페이스임을 표시.

 

public class Main {

    public static void main(String[] args) {
        PrintJava j = () -> System.out.println("JAVA");
        j.print();
    }

    @FunctionalInterface
    interface PrintJava {
        public abstract void print();
    }
}

 

Java 에서 제공하는 함수형 인터페이스

 

인터페이스 반환형 메서드 매개변수
Runnable void run() x
Supplier T get() x
Consumer void accept(T t) 1
Function<T,R> R apply(T t) 1
Pridicate boolean test(T t) 1
UnaryOperator T apply(T t) 1
BiConsumer<T,U> void accpet(T t, U u) 2
BiFunction<U,U,R> R apply(T t, U u) 2
BiPredicate<T, U> boolean test(T t, U u) 2
BinaryOperator T apply(T t, U u) 2

 

  • 매개 변수가 없는 함수형 인터페이스
@FunctionalInterface
public interface Runnable {
  public abstract void run();
}
// 매개변수가 없고 반환 자료형도 없다

@FunctionalInterface
public interface Supplier<T> {
  T get();
}

// Supplier는 매개변수는 없지만 반환 자료형 존재

 

  • 매개 변수가 하나인 함수형 인터페이스

 

@FunctionInterface
public interface Consumer<T>
  void accept(T t);
  
// 1개 매개변수 T가 있지만 반환 자료형 존재 안함

@FunctionalInterface
public interface Function<T, R>
  R apply(T t);
  
// 1개의 매개변수 T와 반환 자료형 R

@FunctionalInterface
public interface Predicate<T>
  boolean test(T t);
  
// 1개의 매개변수 T와 반환 자료형 boolean

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T>
  static <T> UnaryOperator<T> identity()
    return t -> t;
    
// 1개의 매개변수 T와 반환 자료형 T

 

  • 매개 변수가 두 개인 함수형 인터페이스
Function<T, R> - 매개변수 T와 반환 자료형 R

BiFunction<T, U, R> - 첫 번째 매개변수 T, 두 번쨰 매개변수 U, 반환 자료형 R
Predicate<T> - 매개변수 T와 반환 자료형 boolean

BiPredicate<T, U> - 첫 번째 매개변수 T, 두번째 매개변수 U, 반환 자료형 boolean

 


Variable Capture

  • 로컬 변수 캡쳐

final 이거나 effective final인 경우 참조

  • effective fianl은 사실상 final인 변수이다.
  • final 키워드 사용하지 않은 변수를 익명 클래스 구현체 또는 람다에서 참조.
  • 익명 클래스는 새로 scope를 만들지만, 람다는 람다를 감싸는 스콥과 같음

 

참고 : 더 자바: JAVA8

더 자바, Java 8 - 인프런 | 강의 (inflearn.com)

 


매소드 레퍼런스 

 

메소드 시그네쳐 : (name, parameter type)

 

Method Type

(return type, method type parameter, method argument types, exception) 

=> Method Reference

 

(Object name)::(Method name)

//메서드 참조 기본 문법

개체의 이름과 메서드 이름 사이에 더블 콜론(::)을 구분하는 연산자를 사용한다.

 

 

  • static 메서드 참조

 

public class Main {
    public static void main(String[] args) {
        List<String> abc = Arrays.asList("A", "B", "C");
        abc.forEach(Printer::print);
    }
}

class Printer {
    public static void print(Object o) {
        System.out.println(o);
    }
}

 

클래스 내의 static으로 구성된 메서드를 참조 메서드로 사용한다.

 

 

  • 특정 개체의 인스턴스 메서드 참조
public class Main {
    public static void main(String[] args) {
        String hello = "hello world";
        print(hello::toString);
    }

    public static void print(Supplier<String> supplier) {
        System.out.println(supplier.get());
    }
}

 

  • 특정 타입의 임의 개체에 대한 인스턴스 메서드 참조.

 

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal("Dog");

        print(animal::getName);
    }
    
    public static void print(Supplier<String> supplier) {
        System.out.println(supplier.get());
    }
}

 

  • 생성자 참조
(Object name)::new

// 기본 문법
new Object();

() -> new Object() // 람다식 이용한 호출

Object::new // 생성자 참조

 

 

참고 : 코드를 통해 본 빵형의 실전 Java

'JAVA' 카테고리의 다른 글

자바 Hash Map 공부  (0) 2021.10.06
자바 ArrayList 공부  (0) 2021.10.05
제너릭  (0) 2021.02.25
I/O  (0) 2021.02.15
애노테이션  (0) 2021.02.05