java 8 버전을 꽤 오래 사용했었는데, 제대로 공부한 적이 없는 것 같아 조금씩 정리해보는 포스팅을 써본다.
함수형 인터페이스 (Functional Interface)
https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.8
- Default 메소드 이외 단 한 개의 추상 메서드를 가지는 인터페이스
- @FunctionalInterface 어노테이션이 붙은 인터페이스. @FunctionalInterface 어노테이션을 명시적으로 붙임으로써, 컴파일러에게는 해당 인터페이스가 함수형 인터페이스임을 알리고, 추상 메서드를 여러 개 작성하는 경우 또는 해당 인터페이스를 상속하는 경우 컴파일 단계에서 에러를 뱉게 된다.
- 기존에는 자바에서는 기본 데이터 타입들만 값으로 판단하였지만 (ex: Integer, int, Long, String), 함수형 인터페이스 등장으로 인해 함수도 값으로 판단할 수 있게 되었다. 함수 또한 값으로 판단하게 되어 유연한 코드 작성이 가능해졌다.
함수형 인터페이스 선언 예시
package com.tistory.johnmark.functional;
@FunctionalInterface
public interface Validator {
boolean match();
}
함수형 인터페이스인데 추상 메소드가 한 개 이상인 경우 에러 발생
package com.tistory.johnmark.functional;
@FunctionalInterface
public interface Validator {
boolean match();
void print();
}
추상 메소드가 한 개라면 default 메소드나 static 메소드는 상관 없음
package com.tistory.johnmark.functional;
@FunctionalInterface
public interface Validator {
static void printClassName() {
System.out.println("Validator");
}
default String getClassName() {
return "Validator";
}
boolean match();
}
java8 부터는 interface에 default 키워드를 붙인 메소드를 선언할 수 있게 되었다. default 키워드가 붙은 메소드는
해당 인터페이스를 구현한 모든 구현체에 적용이된다.
활용 예시
package com.tistory.johnmark.functional;
import java.util.Arrays;
import java.util.List;
public class FunctionalInterfaceTest {
public static void main(String[] args) {
List<String> names = Arrays.asList("JohnMark", "JeongHyeon", "Bob", "Mark", "Richard", "Narisa");
List<Integer> scores = Arrays.asList(10, 20, 30, 40, 50, 60, 70, 80, 95, 100);
for (String name : names) {
// 함수형 인터페이스를 통해 함수자체를 값으로 넘김
if (isValid(() -> name.startsWith("J"))) {
System.out.printf("Matched Name: [%s]\n", name);
}
}
System.out.println("------------------------------------------");
for (int score : scores) {
// 함수형 인터페이스를 통해 함수자체를 값으로 넘김
if (isValid(() -> score > 50)) {
System.out.printf("Matched Score: [%d]\n", score);
}
}
}
public static boolean isValid(Validator validator) {
return validator.match();
}
}
함수를 값으로 넘겨줄 수 있게 됨으로써, isValid 메소드의 인자인 함수형 인터페이스 Validator의 인스턴스를 람다 표현식으로 만들어 넘김으로 써, 함수형 인터페이스의 추상 메서드 내용을 String, Integer 등 다양한 데이터 타입에 대해 원하는 로직 (1. J로 시작하는 문자열, 2. 50보다 큰 숫자)을 유연하게 작성하고 적용할 수 있게 되었다.
람다 표현식 (Lambda Expressions)
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27
- 람다 표현식은 메소드와 비슷함 (매개변수, 매개변수가 사용되는 body block)
- 간결한 코드 작성 가능
- 함수를 만드는 과정 없이 한 번에 처리 가능
- 람다 표현식을 사용하면서 만드는 무명 함수는 재사용이 불가능함
- 디버깅이 어려움
형태
LambdaExpression:
LambdaParameters -> LambdaBody
예시
() -> {} // No parameters; result is void
() -> 42 // No parameters, expression body
() -> null // No parameters, expression body
() -> { return 42; } // No parameters, block body with return
() -> { System.gc(); } // No parameters, void block body
() -> { // Complex block body with returns
if (true) return 12;
else {
int result = 15;
for (int i = 1; i < 10; i++)
result *= i;
return result;
}
}
(int x) -> x+1 // Single declared-type parameter
(int x) -> { return x+1; } // Single declared-type parameter
(x) -> x+1 // Single inferred-type parameter
x -> x+1 // Parentheses optional for
// single inferred-type parameter
(String s) -> s.length() // Single declared-type parameter
(Thread t) -> { t.start(); } // Single declared-type parameter
s -> s.length() // Single inferred-type parameter
t -> { t.start(); } // Single inferred-type parameter
(int x, int y) -> x+y // Multiple declared-type parameters
(x, y) -> x+y // Multiple inferred-type parameters
(x, int y) -> x+y // Illegal: can't mix inferred and declared types
(x, final y) -> x+y // Illegal: no modifiers with inferred types
출처
https://docs.oracle.com/javase/specs/jls/se8/html/
'Programming > Java' 카테고리의 다른 글
[백 투 더 베이직] 객체지향 SOLID 원칙 (0) | 2021.07.19 |
---|---|
[삽질일기] Arrays.asList 와 ArrayList의 차이 (1) | 2021.07.17 |
객체, 클래스 그리고 인스턴스 (0) | 2021.06.15 |
[Java] CMD 또는 Shell 환경에서 Java 컴파일 및 Jar 파일 만들기 (0) | 2021.01.12 |
[Java8] 윤년, 다음달 말일 계산 (0) | 2020.07.17 |