728x90
메서드 참조
- 메서드를 참조해서 매개 변수의 정보 및 리턴 타입을 알아내어, 람다식에서 불필요한 매개 변수를 제거하는 것이 목적이다.
- 람다식이 하나의 메서드만 호출하는 경우에만 사용할 수 있다.
- 메서드 참조에서 람다식에 있는 인자 전달에 대한 정보를 생략할 수 있는 이유는 함수형 인터페이스에 정의되어 있는 추상 메서드를 호출할 때 전달되는 매개변수 값을 추상 메서드를 구현하고 있는 메서드의 인자로 그대로 전달하기 때문이다.
Consumer<List<Integer>> c1 = x -> Collections.reverse(x); // 람다 표현식
c1.accept(ls);
Consumer<List<Integer>> c2 = Collections::reverse; // 메서드 참조
c2.accept(ls);
- Consumer 함수형 인터페이스의 추상 메서드인 accept() 메서드를 호출 할 때 전달되는 매개변수 값을 그대로 reverse 메서드의 매개변수 값으로 전달하기 때문에 람다식에 있는 인자 전달에 대한 정보를 생략할 수 있다.
메서드 참조의 4가지 유형
- static 메서드의 참조
- 참조변수를 통한 인스턴스 메서드 참조
- 클래스 이름을 통한 인스턴스 메서드 참조
- 생성자 참조
🔍 static 메서드 참조
- 클래스 :: 메서드
람다 | 메서드 참조 |
(x) -> ClassName.method(x) | Class::method |
더보기
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class Prac {
public static void main (String[] args) {
List<Integer> ls = Arrays.asList(1, 3, 5, 7, 9);
ls = new ArrayList<>(ls);
Consumer<List<Integer>> c1 = x -> Collections.reverse(x); // 람다 표현식
c1.accept(ls);
System.out.println(ls);
Consumer<List<Integer>> c2 = Collections::reverse; // 메서드 참조
c2.accept(ls);
System.out.println(ls);
}
}
[9, 7, 5, 3, 1]
[1, 3, 5, 7, 9]
🔍 인스턴스 메서드 참조1 (참조변수를 통한 인스턴스 메서드 참조)
- 참조변수 :: 메서드
람다 | 메서드 참조 |
(obj, x) -> obj.method(x) | Class::method |
더보기
예제1
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class Prac {
public static void main (String[] args) {
List<Integer> ls = Arrays.asList(1, 3, 5, 7, 9);
ls = new ArrayList<>(ls);
JustSort js = new JustSort();
// 람다 표현색
Consumer<List<Integer>> c1 = e -> js.sort(e); // js를 final 선언된 것처럼 다뤄야 한다.
c1.accept(ls);
System.out.println(ls);
// 메서드 참조
Consumer<List<Integer>> c2 = js::sort; // js를 final 선언된 것처럼 다뤄야 한다.
c2.accept(ls);
System.out.println(ls);
}
}
class JustSort {
public void sort(List<?> lst) {
Collections.reverse(lst);
}
}
[9, 7, 5, 3, 1]
[1, 3, 5, 7, 9]
- 람다식이 참조한 지역변수는 final 선언이 된 것처럼 다뤄져야한다. 메서드 참조도 똑같다.
예제2
import java.util.Arrays;
import java.util.List;
public class Prac {
public static void main (String[] args) {
List<String> ls = Arrays.asList("Box", "Robot");
ls.forEach(s -> System.out.print(s)); // 람다 표현식
System.out.println();
ls.forEach(System.out::print); // 메서드 참조
}
}
BoxRobot
BoxRobot
🔍 인스턴스 메서드 참조2 (클래스 이름을 통한 인스턴스 메서드 참조)
/* 람다 표현식 */
ToIntBiFunction<클래스명, 클래스명> bf = (인자1, 인자2) -> 인자1.인스턴스메서드명(인자2)
/* 메서드 참조 */
ToIntBiFunction<클래스명, 클래스명> bf = 클래스명::인스턴스메서드명
- 람다식에서 첫 번째 매개변수인 인자1의 인스턴스 메서드의 매개변수로 두 번째 매개변수인 인자2가 들어올 경우 메서드 참조를 할 수 있다.
- 즉, 인스턴스 없이 인스턴스 메서드를 참조할 수 있는 것이다.
더보기
import java.util.function.ToIntBiFunction;
public class Prac {
public static void main (String[] args) {
IBox ib1 = new IBox(5);
IBox ib2 = new IBox(7);
ToIntBiFunction<IBox, IBox> bf1 = (b1, b2) -> b1.larger(b2); // 람다 표현식
int bigNum1 = bf1.applyAsInt(ib1, ib2);
System.out.println(bigNum1);
ToIntBiFunction<IBox, IBox> bf2 = IBox::larger; // 메서드 참조
int bigNum2 = bf2.applyAsInt(ib1, ib2);
System.out.println(bigNum2);
}
}
class IBox {
private int n;
public IBox(int i) {
n = i;
}
public int larger(IBox b) {
if(n > b.n)
return n;
return b.n;
}
}
7
7
- 람다식에서 호출하는 메서드 larger()가 첫 번째 인자인 b1의 인스턴스 메서드이며 larger() 메서드의 매개변수로 두 번째 인자인 b2가 전달될 경우 메서드 참조를 할 수 있다.
🔍 생성자 참조
- 람다식으로 인스턴스를 생성하고 이의 참조 값을 반환해야 하는 경우 메서드 참조로 대체 할 수 있다.
람다 | 메서드 참조 |
(a, b) -> new 클래스(a) | Class::new |
더보기
예제1
import java.util.function.Function;
public class Prac {
public static void main (String[] args) {
char[] src = {'R', 'o', 'b', 'o', 't'};
Function<char[], String> f1 = ar -> new String(ar); // 람다 표현식
String str = f1.apply(src);
System.out.println(str);
Function<char[], String> f2 = String::new; // 메서드 참조
str = f2.apply(src);
System.out.println(str);
}
}
Robot
Robot
예제2
import java.util.function.Supplier;
public class Prac {
public static void main (String[] args) {
Supplier<MyClass> f1 = () -> new MyClass();
MyClass m1 = f1.get();
System.out.println(m1);
Supplier<MyClass> f2 = MyClass::new;
MyClass m2 = f2.get();
System.out.println(m2);
Supplier<String> f3 = String::new;
String str = f3.get();
}
}
class MyClass {
@Override
public String toString() {
return "생성자";
}
}
생성자
생성자
- 매개변수가 필요없는 생성자를 통해 인스턴스를 생성할 때는 Supplier 함수형 인터페이스를 사용하면 된다.
예제3
import java.util.function.Function;
public class Prac {
public static void main (String[] args) {
Function<Integer, MyClass> f1 = i -> new MyClass(i); // 람다 표현식
MyClass m1 = f1.apply(1);
System.out.println(m1);
Function<Integer, MyClass> f2 = MyClass::new; // 메서드 참조
MyClass m2 = f2.apply(5);
System.out.println(m2);
Function<Integer, int[]> fArr1 = x -> new int[x]; // 람다 표현식
int[] arr1 = fArr1.apply(10); // 배열 크기가 10인 배열 생성
Function<Integer, int[]> fArr2 = int[]::new; // 메서드 참조
int[] arr2 = fArr1.apply(20); // 배열 크기가 20인 배열 생성
}
}
class MyClass {
int i;
MyClass(int i) {
this.i = i;
}
@Override
public String toString() {
return i +"";
}
}
1
5
- 매개변수가 필요한 생성자라면 매개변수의 개수에 따라 알맞은 함수형 인터페이스를 사용해야 한다.
- Function 함수형 인터페이스를 통해 배열을 만들 수 있다.
예제4
import java.util.function.BiFunction;
public class Prac {
public static void main (String[] args) {
BiFunction<Integer, String, MyClass> bf1 = (i, s) -> new MyClass(i, s);
MyClass m1 = bf1.apply(1, "하");
System.out.println(m1);
BiFunction<Integer, String, MyClass> bf2 = MyClass::new;
MyClass m2 = bf2.apply(5, "상");
System.out.println(m2);
}
}
class MyClass {
int i;
String s;
MyClass(int i, String s) {
this.i = i;
this.s = s;
}
@Override
public String toString() {
return i + ", " + s;
}
}
1, 하
5, 상
- 생성자의 매개변수가 2개가 필요한 경우 BiFunction 함수형 인터페이스를 이용한다.
728x90
'[자바] > 자바' 카테고리의 다른 글
[자바] JVM이란? (0) | 2022.05.06 |
---|---|
[Java] Optional<T> 클래스 (0) | 2022.02.07 |
[Java] 함수형 인터페이스 (0) | 2022.02.03 |
[Java] 내부 클래스, 네스티드(Nested) 클래스, 익명 클래스 (0) | 2022.01.27 |
[Java] 애노테이션 (annotation) (0) | 2022.01.26 |