package me.whiteship.java8to11._01_fi;
@FunctionalInterface // 어노테이션을 달아서 명시해준다.
public interface RunSomething {
int plusTen(int num);
// java8부터 interface 에 쓰일 수 있는 함수의 형태가 다양해졌다.
// static method, default method 는 functional interface의 메소드로 카운트하지 않아서
// 아래와 같이 함수형 인터페이스에도 같이 사용 가능!
static void printName(String name) {
System.out.println(name);
}
default void printAge(int age) {
System.out.println(age);
}
}
@Test
void 익명내부클래스로_표현한다() {
RunSomething runSomething = new RunSomething() {
@Override
public int plusTen(int num) {
return num + 10;
}
};
assertThat(runSomething.plusTen(10)).isEqualTo(20);
}
@Test
void 람다로_표현한다() {
RunSomething runSomething = num -> num + 10;
assertThat(runSomething.plusTen(10)).isEqualTo(20);
}
1-2. 람다 표현식 (Lambda Expression)
함수형 인터페이스의 인스턴스를 만드는 방법으로 쓰일 수 있다.
코드를 줄일 수 있다.
메소드 매개변수, 리턴타입, 변수로 만들어 사용할 수 있다.
1-3. 자바에서 함수형 프로그래밍시 주의할 점
순수함수(pure function)이다.
사이드 이펙트가 없다. 함수 밖에 있는 값을 변경하지 않는다.
상태가 없다. 함수 밖에 있는 값을 사용하지 않는다.
고차함수(higher-order function)
함수가 함수를 매개변수로 받을 수 있고, 함수를 리턴할 수도 있다.
불변성 : 같은 매개변수를 넣으면 항상 같은 값이 나온다.
@Test
void 일급함수로사용할수있다() {
RunSomething runSomething = num -> num + 10;
assertThat(runSomething.plusTen(10)).isEqualTo(20);
}
@Test
void 순수함수이다() {
int baseNum = 10;
RunSomething runSomething = num -> baseNum += num; // 컴파일 에러
runSomething.plusTen(10);
}
@Test
void 고차함수이다() {
RunFactory runFactory = new RunFactory();
RunSomething runSomething = runFactory.runSomething(num -> num + 100); //매개변수로 전달
assertThat(runSomething.plusTen(10)).isEqualTo(110);
}
@Test
void 상태가없어야한다() {
int baseNum = 15;
RunSomething runSomething = num -> baseNum + num; // 외부 상태값을 사용함
assertThat(runSomething.plusTen(10)).isEqualTo(25);
}
2. 자바에서 제공하는 함수형 인터페이스
Java가 기본으로 제공하는 함수형 인터페이스가 존재한다.
java.lan.function package 에 속해있다.
자바 차원에서 미리 자주 사용할만한 함수 인터페이스를 만들어둔 것이다.
2-1. Function<T, R>
T 타입을 받아서 R타입을 리턴하는 인터페이스
apply
andThen
compose
public class Plus10 implements Function<Integer, Integer> {
@Override
public Integer apply(Integer integer) {
return integer + 10;
}
}
public class FunctionInterface {
@Test
void applyTest() {
//구현체
Plus10 plus10 = new Plus10();
assertThat(plus10.apply(10)).isEqualTo(20);
//lambda
Function<Integer, Integer> plus11 = num -> num + 11;
assertThat(plus11.apply(10)).isEqualTo(21);
}
@Test
void composeTest() {
Function<Integer, Integer> plus10 = num -> num + 10;
Function<Integer, Integer> multiply5 = num -> num * 5;
Function<Integer, Integer> both = plus10.compose(multiply5);
assertThat(both.apply(2)).isEqualTo(20);
}
@Test
void andThenTest() {
Function<Integer, Integer> plus10 = num -> num + 10;
Function<Integer, Integer> multiply5 = num -> num * 5;
Function<Integer, Integer> both = plus10.andThen(multiply5);
assertThat(both.apply(2)).isEqualTo(60);
}
}