티스토리 뷰
함수형 인터페이스(Functional Interface)란?
추상 메소드를 단 하나만 가지고 있는 SAM (Single Abstract Method) 인터페이스입니다.
@FuncationInterface 애노테이션을 가지고 있습니다.
함수형 인터페이스를 더 알아보기 전에 우선 람다 표현식 및 메소드 레퍼런스부터 알아보겠습니다.
람다 표현식(Lambda Expressions)이란?
함수형 인터페이스의 인스턴스를 만드는 방법으로 쓰일 수 있습니다.
메소드 매개변수, 리턴 타입, 변수로 만들어 사용할 수도 있습니다.
그리고 코드를 확연히 줄일 수 있습니다.
RunSomething runSomething = new RunSomething() {
@Override
public int doIt(int number) {
return number + 10;
}
};
RunSomething rambda = number -> number + 10;
표현식 : ( 인자 리스트 ) -> { 바디 }
인자 리스트
- 인자가 없을 때 : ()
- 인자가 한 개 일 때 : (one) 또는 one
- 인자가 여러개 일 때 : (one, two)
- 인자의 타입은 생략 가능하고 명시할 수도 있습니다. : (Integer one, Integer two)
바디
- 화살표 오른쪽에 함수 본문을 정의합니다.
- 여러 줄인 경우에 {}를 사용해서 묶습니다.
- 한 줄인 경우에 생략 가능하며, return도 생략이 가능합니다.
변수 캡처 (Variable Capture)
- 로컬변수캡처
final이거나 effective final 인 경우에만 참조할 수 있습니다.
concurrency 문제가 생길 수 있어서 컴파일에러가 발생합니다.
public static void main(String[] args) { int baseNumber = 10; RunSomething rambda = number ->{ return baseNumber; }; }
- effective final
자바 8부터 지원하는 기능으로 “사실상" final인 변수입니다.
final 키워드 사용하지 않은 변수를 익명 클래스 구현체 또는 람다에서 참조할 수 있습니다.
- 익명 클래스 구현체와 달리 ‘쉐도 윙(Shadowing)’ 하지 않습니다.
익명 클래스는 새로 스코프를 만들지만, 람다는 람다를 감싸고 있는 스코프와 같습니다.
그래서 람다 스코프와 람다를 감싸고 있는 스코프(main Method)에 똑같은 변수명을 쓰지 못합니다.
- 쉐도 윙이란 ?
외부 클래스의 변수명과 내부 클래스의 변수명 그리고 내부 클래스 내의 메서드 파라미터명이 같을 경우
외부 클래스의 변수가 가려지면서, 내부클래스의 변수나 내부 클래스 내의 파라미터가 쓰여집니다.
- 쉐도 윙이란 ?
메소드 레퍼런스란?
람다가 하는 일이 기존 메소드 또는 생성자를 호출하는 거라면, 메소드 레퍼런스를 사용하면 람다와 다르게 간결하게 표현할 수 있다.
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;
}
}
// 스태틱 메소드 참조
UnaryOperator<String> hi = Greeting::hi;
// 특정 객체의 인스턴스 메소드 참조
Greeting greeting = new Greeting();
UnaryOperator<String> hello = greeting::hello;
// 임의 객체의 인스턴스 메소드 참조
String [] name = {"minkyu", "com", "example"};
Arrays.sort(name, String::compareToIgnoreCase);
//생성자 참조
Supplier<Greeting> newGreeting = Greeting::new;
메소드 참조하는 방법
- 스태틱 메소드 참조 > 타입::스태틱 메소드
- 특정 객체의 인스턴스 메소드 참조 > 객체 레퍼런스::인스턴스 메소드
- 임의 객체의 인스턴스 메소드 참조 > 타입::인스턴스 메소드
- 생성자 참조 > 타입::new
메소드 또는 생성자의 매개변수로 람다의 입력값을 받습니다.
리턴 값 또는 생성한 객체는 람다의 리턴 값입니다.
자바에서 기본적으로 제공하는 함수형 인터페이스가 있습니다.
java.util.function 패키지 중 자주 사용할만한 함수 인터페이스들을 자세히 살펴보겠습니다.
@Test
public void functionTest(){
Function<Integer, Integer> plus10 = (number) -> number + 10;
Function<Integer, Integer> multiply2 = (number) -> number * 2;
Function<Integer, Integer> functionCompose = plus10.compose(multiply2);
Function<Integer, Integer> functionAndThen = plus10.andThen(multiply2);
Assertions.assertThat(plus10.apply(2)).isEqualTo(12);
Assertions.assertThat(multiply2.apply(2)).isEqualTo(4);
Assertions.assertThat(functionCompose.apply(2)).isEqualTo(14);
Assertions.assertThat(functionAndThen.apply(2)).isEqualTo(24);
}
Function<T, R>
T타입을 받아서 R타입을 리턴하는 함수 인터페이스입니다.
- R apply(T t)
- 함수 조합용 메소드
- andThen
- compose
@Test
public void biFunctionTest(){
Function<Integer, Integer> plus10 = (number) -> number + 10;
BiFunction<Integer, Integer, Integer> biFunctionSum = (number, number2) -> number + number2;
BiFunction<Integer, Integer, Integer> biFunctionAndThen = biFunctionSum.andThen(plus10);
Assertions.assertThat(biFunctionSum.apply(4,8)).isEqualTo(12);
Assertions.assertThat(biFunctionAndThen.apply(4,8)).isEqualTo(22);
}
BiFunction<T, U, R>
두 개의 값(T, U)을 받아서 R 타입을 리턴하는 함수 인터페이스입니다.
- R apply(T t, U u)
- 함수 조합용 메소드
- andThen
@Test
public void consumerTest(){
ArrayList<Integer> list = new ArrayList<>();
Consumer<Integer> addList = (age) -> list.add(age);
Consumer<Integer> addListPlus10 = (name) -> list.add(name + 10 );
Consumer<Integer> consumerAndThen = addList.andThen(addListPlus10);
addList.accept(30);
Assertions.assertThat(list.size()).isEqualTo(1);
Assertions.assertThat(list.get(0)).isEqualTo(30);
list.clear();
consumerAndThen.accept(30);
Assertions.assertThat(list.size()).isEqualTo(2);
Assertions.assertThat(list.get(0)).isEqualTo(30);
Assertions.assertThat(list.get(1)).isEqualTo(40);
}
Consumer<T>
T타입을 받아서 아무 값도 리턴하지 않는 함수 인터페이스입니다.
- void accept(T t)
- 함수 조합용 메소드
- andThen
@Test
public void supplierTest(){
Supplier<Integer> getAge = () -> 30;
Assertions.assertThat(getAge.get()).isEqualTo(30);
}
- T get()
@Test
public void predicateTest(){
Predicate<Integer> isEven = (number) -> number % 2 == 0;
Predicate<Integer> isTen = (number) -> number.equals(10);
Assertions.assertThat(isEven.test(10)).isEqualTo(true);
Assertions.assertThat(isEven.and(isTen).test(10)).isEqualTo(true);
Assertions.assertThat(isEven.or(isTen).test(4)).isEqualTo(true);
Assertions.assertThat(isEven.negate().test(2)).isEqualTo(false);
}
Predicate<T>
T타입을 받아서 boolean을 리턴하는 함수 인터페이스입니다.
- boolean test(T t)
- 함수 조합용 메소드
- and
- or
- negate
@Test
public void unaryOperator(){
UnaryOperator<Integer> plusTen = (number) -> number + 10;
Assertions.assertThat(plusTen.apply(10)).isEqualTo(20);
}
UnaryOperator<T>
Function<T, R>의 특수한 형태로, 입력값 하나를 받아서 동일한 타입을 리턴하는 함수 인터페이스입니다.
- R apply(T t)
- 함수 조합용 메소드
- andThen
- compose
@Test
public void BinaryOpreator(){
BinaryOperator<Integer> binarySum = (number, number2) -> number + number2;
Assertions.assertThat(binarySum.apply(5,8)).isEqualTo(13);
}
BinaryOperaor<T>
BiFunction<T, U, R>의 특수한 형태로, 동일한 타입의 입력값 두 개를 받아 리턴하는 함수 인터페이스입니다.
- R apply(T t, U u)
- 함수 조합용 메소드
- andThen
끝으로 자바에서 함수형 프로그래밍 대해 살펴보겠습니다.
순수 함수(Pure function)란?
함수 밖에 있는 값을 변경하거나 사용하지 않고, 동일한 입력에 대하여 항상 동일한 출력을 반환하는 함수입니다.
- Side Effect가 없다. (함수 밖에 있는 값을 변경하지 않습니다.)
- 상태가 없다. (함수 밖에 있는 값을 사용하지 않습니다.)
고차 함수(Higher-Order Function)란?
함수가 함수를 매개변수로 받을 수 있고 함수를 리턴할 수도 있습니다.
이로써 공부한 내용을 간략히 정리해보았습니다.
감사합니다.
출처
'Java' 카테고리의 다른 글
Java8 Optional API (0) | 2022.05.06 |
---|---|
Java8 Stream API (0) | 2022.05.04 |
자바 인터페이스(Interface) (0) | 2022.04.13 |
애노테이션 프로세서(Annotation processor) (0) | 2022.04.06 |
프록시 패턴(Proxy Pattern) (0) | 2022.04.05 |
- Total
- Today
- Yesterday
- dromos
- optional api
- 프록시패턴
- 애노테이션
- 람다표현식
- 자바 프록시 패턴
- 실행 엔진
- 깃 기초
- javaagent
- jvm
- 코드 커버리지
- JRE와 JDK의 차이점
- bytebuddy
- 애노테이션 프로세서
- Java Reflection
- Reflection
- classloder
- javassist
- java
- java abstractprocessor
- java proxy pattern
- JVM 구조
- Functional Interface
- 자바 리플렉션
- Annotation Processor
- java11 optional
- 클래스로더
- 바이트 코드
- 리플렉션
- java optional
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |