이 글은 백기선 님의 더 자바, Java 8 강의를 듣고 복습 차원에서 적은 글입니다.
Java 8 에서는 무엇이 바뀌었을까? 현재 자바 개발자 중 약 83%가 사용 중이라고 한다.
이 글을 통해서 확실히 공부해놓으면 좋을 것 같다.
함수형 인터페이스 (Function Interface)
- 추상 메소드를 딱 하나만 가지고 있는 인터페이스이다.
- SAM(Single Abstract Method) 인터페이스라고도 불린다.
- @FuncationInterface 어노테이션을 가지고 있는 인터페이스이다.
@FunctionalInterface
public interface Foo {
void doIt();
}
람다 표현식 (Lambda Expressions)
- 함수형 인터페이스의 인스턴스를 만드는 방법으로 사용된다.
- 코드를 간략하게 만들 수 있다.
- 메서드 매개변수, 리턴 타입, 변수로 만들어 사용할 수도 있다.
기본 함수형 인터페이스
- Function <T, R>
- Supplier <T>
- Consumer <T>
- Function <T, R>
- Predicate <T>
이외에 많은 함수형 인터페이스를 여기서 확인하실 수 있습니다.
그래서 함수형 인터페이스 그리고 람다는 뭐라는 거야?
잠시 자바스크립트 코드를 보자!
자주 사용하는 더하기 함수를 만들고 싶다고 가정하자!
var add = function (a, b) {
return a + b
};
add(1, 1) // 2
add(10, 3) // 13
너무나 사용하기가 편하다. 자바도 이렇게 사용하면 편하고 재사용성도 좋을 것 같은데...
그래서 자바도 함수형 인터페이스라는 것을 만들었다. 그리고 람다라는 녀석도 만들었다.
@FunctionalInterface
public interface Add {
int add(int a, int b);
}
public static void main(String[] args) {
// 익명 클래스
Add Func1 = new Add() {
@Override
public int add(int a, int b) {
return a + b;
}
};
System.out.println(Func1.add(1, 1)); // 2
System.out.println(Func1.add(10, 3)); // 13
// 람다
Add Func2 = (a, b) -> {
return a + b;
};
System.out.println(Func2.add(1, 1)); // 2
System.out.println(Func2.add(10, 3)); // 13
}
기존의 익명 클래스 방식에서 람다 방식으로 편하게 사용이 가능해졌다.
그리고 Add라는 커스텀 함수형 인터페이스는 구현이 간단해서 기본 함수형 인터페이스(intBinaryOperator)가 존재한다.
즉 람다는 함수형 인터페이스와 셋뚜 셋뚜 이다. 또한 람다만의 특징이 있는데 변수의 참조 범위가 다르다.
public static void main(String[] args) {
Main main = new Main();
main.run();
}
private void run() {
final int baseNumber = 10;
// 로컬 클래스
class LocalClass {
void printBaseNumber() {
int baseNumber = 11; // 재선언 가능하다.
System.out.println(baseNumber);
}
};
// 익명 클래스
Consumer<Integer> integerConsumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
int baseNumber = 11; // 재선언 가능하다.
System.out.println(baseNumber);
}
};
// 람다
IntConsumer printInt = (i) -> {
// int baseNumber = 11; // 재선언 불가능하다. 람다를 감싸고 있는 Scope과 같다.
System.out.println(i + baseNumber);
};
printInt.accept(10);
}
마지막으로 람다는 메소드 레퍼런스를 사용하여 더욱더 간결하게 표현할 수 있다.
(아직 완벽하게 이해는 못하겠다.)
스테틱 메스드 참조 | 타입:스테틱 메소드 |
특정 객체의 인스턴스 메소드 참조 | 객체 레퍼런스:: 인스턴스 메소드 |
생성자 참조 | 타입::new |
임의 객체의 인스턴스 메소드 참조 | 타입::인스턴스 메소드 |
public class Greeting {
private String name;
public Greeting() {
}
public Greeting(String name) {
this.name = name;
}
public String hello(String name) {
return "hello " + name;
}
public String hi(String name) {
return "hi " + name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class App {
public static void main(String[] args) {
// 스태틱 메소드 참조법
Greeting greeting = new Greeting();
UnaryOperator<String> hello = greeting::hello;
System.out.println(hello.apply("giuly"));
// 생성자 참조
Supplier<Greeting> newGreeting = Greeting::new;
System.out.println(newGreeting);
// 특정 객체의 인스턴스 메소드 참조
Function<String, Greeting> funcGreeting = Greeting::new;
Greeting str = funcGreeting.apply("giuly");
System.out.println(str.getName());
// 임의 객체의 인스턴스 메소드 참조
String[] names = {"giuly", "jihuni1026", "jihun"};
Arrays.sort(names, String::compareToIgnoreCase);
System.out.println(Arrays.toString(names));
}
}
언젠가 익숙해지겠지 ...
'BackEnd > Java' 카테고리의 다른 글
[Java] Enum, Const 이야기 (0) | 2023.05.07 |
---|---|
[Java] JUnit5 애플리케이션을 테스트하는 다양한 방법 이야기 2부 (0) | 2020.09.22 |
[Java] 컬렉션 프레임워크(collection framework) 이야기 2부 - Set (0) | 2020.09.18 |
[Java] 컬렉션 프레임워크(collection framework) 이야기 1부 - List (0) | 2020.09.17 |
[Java] JUnit5 애플리케이션을 테스트하는 다양한 방법 이야기 1부 - Assertion (0) | 2020.09.15 |
댓글