학습주제
- 람다식 사용법
- 함수형 인터페이스
- 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 |