함수형 인터페이스
람다식이 메서드와 동등한 것처럼 보이지만, 사실 람다식은 익명 클래스의 객체와 동등하다.
* 익명 클래스 : InnerClass의 한 종류로 이름이 없는 객체를 만들 수 있다.
메서드를 호출하려면 참조변수가 있어야 한다. 람다식으로 정의된 익명 객체의 메서드는 참조변수가 있어야 호출할 수 있다.
데이터타입 f = a -> a + a;
위의 코드에서 데이터타입은 참조형이다. 참조형이 가능하단 말은 String과 같이 클래스이거나 List같이 인터페이스가 올 수 있다는 말이다. 그리고 람다식과 동등한 메서드가 정의돼있어야 한다.(Interface면 구현, 클래스라면 오버라이딩으로 가능하다)
위에서 언급한 익명클래스 객체는 아래와 같이 생성하고 동작할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
interface MyFunction{
void run();
}
public static void main(String[] args) {
MyFunction f = new MyFunction() {
@Override
public void run() {
System.out.println("This is anonymous function");
}
f.run();
};
//This is anonymous function |
cs |
위 코드를 람다식으로 대체하면
1
2
3
4
5
6
7
8
9
|
interface MyFunction{
void run();
}
public static void main(String[] args) {
MyFunction f = () -> System.out.println("This is anonymous function");
f.run();
};
//This is anonymous function |
cs |
Q - f에서 구현한 람다식은 run에 대해 언급을 하지 않았는데 어떻게 동작하는 거죠?
A - 하나의 메서드가 선언된 인터페이스를 정의하면 추론이 가능합니다. 대신 하나의 추상 메서드(1:1 매칭)만 정의되어 있어야 한다는 제약이 있습니다.
인터페이스를 정의해서 람다식을 다루는 것은 기존의 자바의 규칙들을 어기지 않으면서도 자연스럽다 하여 인터페이스를 통해 람다식을 다루기로 결정되었으며, 람다식을 다루기 위한 인터페이스를 '함수형 인터페이스(functional interface)'라 부르기로 했다.
@FunctionalInterface를 붙이면, 컴파일러가 함수형 인터페이스를 올바르게 정의했는지 확인해주므로, 꼭 붙이도록 한다.
매개변수로 받을 수 있는 람다식
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@FunctionalInterface
interface MyFunction{ void run();
}
public static void execute(MyFunction f) {
f.run();
}
public static void main(String[] args) {
execute(() -> System.out.println("This is anonymous function"));
}
//This is anonymous function
|
cs |
람다식을 참조변수로 다룰 수 있다는 것은 메서드를 통해 람다식을 주고받을 수 있다는 것을 의미한다.
사실상 메서드가 아니라 객체를 주고받는 것이라 근본적으로 달라진 것은 없지만, 코드가 더 간결해지는 특징이 있다.
람다식의 타입과 형변환
함수형 인터페이스로 람다식을 참조할 수 있는 것이지 람다식의 타입이 함수형 인터페이스의 타입과 일치하는 것은 아니다. 람다식은 익명 객체이고 익명 객체는 타입이 없다.
정확히는 타입이 있지만 컴파일러가 임의로 이름을 정한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@FunctionalInterface
interface MyFunction{
void run();
}
public static void main(String[] args) {
MyFunction f = () -> System.out.println("형변환 및 타입확인");
Object obj = (Object) f; String str = (String) obj.toString();
System.out.println(str);
}
//Package.Lambda$$Lambda$4/0x0000000800061840@3d04a311
|
cs |
람다식의 외부 변수 참조
람다식도 익명 객체, 익명 클래스의 인스턴스이므로 람다식에서 외부에 선언된 변수에 접근하는 규칙은 익명 클래스와 같다.
- 람다식 내에서 사용하는 지역변수는 final이 붙지 않았어도 상수로 간주된다.
- 람다식 내에서 사용하는 지역변수는 람다식 내에서나 다른 어느 곳에서도 변경할 수 없다.
- 반면에 외부 클래스의 인스턴스 변수는 변경이 가능하다.
- 람다식 매개변수로 외부 지역변수와 같은 이름의 변수는 허용되지 않는다.
-> 람다식(Lambda) 정리하기 (2. 함수형 인터페이스 : 응용편) 바로가기 : tosuccess.tistory.com/182
[개인 공부를 위한 정리입니다. 참고용으로만 활용하세요]
Reference
Java의 정석 (남궁 성 지음)
'프로그래밍 언어 > JAVA(자바)' 카테고리의 다른 글
[자바/java] 람다식(Lambda) 정리하기 (3. 람다식의 다양한 형태) (0) | 2021.05.07 |
---|---|
[자바/java] 람다식(Lambda) 정리하기 (2. 함수형 인터페이스(Functional Interface) : 응용) (0) | 2021.04.15 |
[자바/java] 람다식(Lambda) 정리하기 (1. 개념) (0) | 2021.04.11 |
[자바/java] 효율적인 배열 복사 System.arrayCopy (0) | 2020.09.24 |
[자바/java] 이차원 배열 90도 회전시키기, int[][] rotate (0) | 2020.09.09 |