티스토리 뷰
1. 함수형 인터페이스
2. 자바에서 제공하는 함수형 인터페이스
3. 람다 표현식
4. 메소드 참조
1. 함수형 인터페이스
- 추상메소드를 하나만 가지고 있는 인터페이스
- @FuncationInterface 어노테이션을 가지고 있는 인터페이스
// functional interface 를 annotation으로 정의 가능
// 선언 규칙위반일 때 컴파일 오류 발생 : 좀 더 견고하게 관리할 수 있다.
@FunctionalInterface
public interface FunctionalInterface01 {
// 추상 메소드를 하나만 가지고 있는 인터페이스
// abstract 생략 가능
void doIt();
// static, default 메소드 정의 가능(java 8 에 추가된 기능)
// public 생략 가능
static void printName() {
System.out.println("mandy");
}
default void printAge() {
System.out.println("20");
}
}
2. 자바에서 제공하는 함수형 인터페이스
1) Function : <parameter type, return type>
R apply(T t) : 파라미터 O, 리턴 X
> 클래스로 선언
import java.util.function.Function;
public class Plus5 implements Function<Integer, Integer> {
@Override
public Integer apply(Integer integer) {
return integer+5;
}
}
// main 메소드
Plus5 plus5 = new Plus5();
System.out.println(plus5.apply(2)); // 7
> 람다 표현식으로 선언
Function<Integer, Integer> plus10 = number -> number + 10;
Function<Integer, Integer> muliply2 = number -> number * 2;
//UnaryOperator<Integer> muliply2 = number -> number + 10; // 인자값과 리턴값이 같은 경우 사용가능
// 함수 조합
// plus10.compose(muliply2) : muliply2 > plus10
// plus10.andThen(muliply2) : plus10 > muliply2
System.out.println(plus10.compose(muliply2).apply(2)); // 14
System.out.println(plus10.andThen(muliply2).apply(2)); // 24
2) Consumer : <parameter type>
void accept(T t) : 파라미터 O, 리턴 X
Consumer<Integer> printT = number -> System.out.println(number);
printT.accept(10); // 10
3) Supplier : <return type>
T get() : 파라미터 X, 리턴 O
Supplier<String> getName = () -> "mandy";
System.out.println(getName.get()); // mandy
4) Predicate : <parameter type> return boolean
boolean test(T t) : 파라미터 O,, 리턴 O(타입 : boolean)
Predicate<String> startsWith = (name) -> "mandykr".startsWith(name);
Predicate<String> endsWith = (name) -> "mandykr".endsWith(name);
Predicate<String> startsOrEndsWith = startsWith.or(endsWith);
System.out.println(startsOrEndsWith.test("mandy")); // true
추가 인터페이스 확인 : java.lang.function 패키지
3. 람다 표현식
쉐도윙 : 외부 스콥의 변수와 로컬 변수의 이름이 같은 경우 외부 변수가 로컬 변수에 가려짐.
private void run() {
// effective final : 사실상 final인 경우(재정의가 발생하지 않는 경우) final 키워드 생략가능
int baseNumber = 10;
// 1. 로컬 클래스
class localClass {
void printBaseNumber(int baseNumber) { // 쉐도잉
System.out.println(baseNumber);
}
}
// 2. 익명 클래스
IntConsumer intConsumer = new IntConsumer() {
@Override
public void accept(int baseNumber) { // 쉐도잉
System.out.println(baseNumber);
}
};
// 3. 람다
// 익명 클래스는 새로 스콥을 만들지만, 람다는 람다를 감싸고 있는 스콥과 같다.
// 쉐도윙이 일어나지 않고 컴파일 에러 발생(baseNumber가 이미 정의되어 있음)
//IntConsumer lambdaIntConsumer = (baseNumber) -> System.out.println(baseNumber);
// > 로컬변수 캡쳐
// final 이거나 effective final 인 경우에만 참조 가능
// 그렇지 않은 경우 컴파일 에러(concurrency)
IntConsumer lambdaIntConsumer = (number) -> System.out.println(baseNumber);
// effective final 이 깨지는 경우 람다에서 호출할 수 없음(컴파일 에러)
// baseNumber++;
}
4. 메소드 참조
FunctionalInterface interface = 추상 메소드의 body;
public class Greeting {
private String name;
public Greeting() {
}
public Greeting(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String hello(String name) {
return "hello" + name;
}
public static String hi(String name) {
return "hi" + name;
}
}
1) static 메소드 참조
UnaryOperator<T> extends Function<T, T> : 입력값과 리턴값이 같은 Function인 경우 사용
UnaryOperator<String> hi = Greeting::hi;
System.out.println(hi.apply("mandy"));
// 익명 클래스로 변환해 생각해보면 ...
UnaryOperator<String> hi = new UnaryOperator<String>() {
@Override
public String apply(String name) {
return "hi" + name;
}
};
2) 인스턴스 메소드 참조
Greeting greeting = new Greeting();
UnaryOperator<String> hello = greeting::hello;
System.out.println(hello.apply("mandy"));
3) 임의 객체의 인스턴스 메소드 참조
String[] names = {"mandy", "keesun", "toby"};
// 익명클래스로 표현
Arrays.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return 0;
}
});
// 람다로 표현
Arrays.sort(names, (o1, o2) -> 0);
// Comparator 객체(CASE_INSENSITIVE_ORDER)의 인스턴스 메소드 참조 사용
Arrays.sort(names, String::compareToIgnoreCase);
// String class
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
public int compareToIgnoreCase(String str) {
return CASE_INSENSITIVE_ORDER.compare(this, str);
}
4) 생성자 참조(default)
Greeting 타입을 리턴하는 default 생성자
Supplier<Greeting> greetingSupplier = Greeting::new;
System.out.println(greetingSupplier.get().hello("mandy"));
5) 생성자 참조(parameter)
String 타입을 인자로 받아 Greeting 타입을 리턴하는 생성자
Function<String, Greeting> greetingFunction = Greeting::new;
Greeting mandy = greetingFunction.apply("mandy");
System.out.println(mandy.getName());
출처
https://www.inflearn.com/course/the-java-java8 더 자바, Java 8(백기선)
728x90
'Java > Java 8' 카테고리의 다른 글
[java 8] 3-1. Stream (생성, 중간 연산, 최종 연산) (0) | 2021.12.29 |
---|---|
[java 8] 4. Optional (0) | 2021.12.18 |
[java 8] 3. Stream (0) | 2021.12.17 |
[java 8] 1-1. 함수형 인터페이스와 람다 (메소드 참조) (0) | 2021.12.17 |
[java 8] 2. 인터페이스의 변화 (0) | 2021.12.02 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- http
- 육각형 아키텍처
- 클린코드
- 도메인 모델링
- ATDD
- TDD
- Spring
- clean code
- Stream
- HTTP 헤더
- MySQL
- kafka
- Git
- Ubiquitous Language
- spring rest docs
- 학습 테스트
- Spring Boot
- named query
- 계층형 아키텍처
- 이벤트 스토밍
- Spring Data JPA
- java8
- 스프링 카프카 컨슈머
- 트랜잭셔널 아웃박스 패턴
- 스프링 예외 추상화
- JPA
- 폴링 발행기 패턴
- 마이크로서비스 패턴
- mockito
- H2
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함