메소드 참조의 4가지 유형과 메소드 참조의 장점
● static 메소드의 참조
● 참조 변수를 통한 인스턴스 메소드 참조
● 클래스 이름을 통한 인스턴스 메소드 참조
● 생성자 참조
기본적으로 람다식보다 조금 더 코드를 단순하게 할 수 있다는 장점이 있다.
일부 람다식을 메소드 참조로 대신하게 할 수 있다.
static 메소드의 참조 : 람다식 기반 예제
Consumer<T> void accept(T t)
Collections 클래스의 reverse 메소드 기반 예제
public static void reverse(List<?> list) // 저장 순서를 뒤집는다.
class ArrangeList {
public static void main(String[] args) {
List<Integer> ls = Arrays.asList(1, 3, 5, 7, 9);
ls = new ArrayList<>(ls);
Consumer<List<Integer>> c = l -> Collections.reverse(l); // reverse 메소드 호출 중심의 람다식
c.accept(ls); // 순서 뒤집기 진행
System.out.println(ls); // 출력
}
}
static 메소드의 참조 : 메소드 참조 기반으로 수정
Consumer<T> void accept(T t)
Consumer<List<Integer>> c = l -> Collections.reverse(l);
→ Consumer<List<Integer>> c = Collections::reverse;
accept 메소드 호출 시 전달되는 인자를 reverse 메소드를 호출하면서 그대로 전달한다는 약속에 근거한 수정
void accept(T t)
void reverse(List<?> list)
accept로 전달된 것 reverse로 그대로. . .
인스턴스 메소드 참조 1 : effectively final
Consumer<T> void accept(T t)
class JustSort {
public void sort(List<?> lst) { // 인스턴스 메소드
Collections.reverse(lst);
}
}
class ArrangeList3 {
public static void main(String[] args) {
List<Integer> ls = Arrays.asList(1, 3, 5, 7, 9);
ls = new ArrayList<>(ls);
JustSort js = new JustSort(); // js는 effectively final (사실상 상수) - js가 참조하는 인스턴스는 바뀌지 않음!
Consumer<List<Integer>> c = e -> js.sort(e); // 람다식 기반
c.accept(ls);
System.out.println(ls);
}
}
[9, 7, 5, 3, 1]
인스턴스 메소드 참조 1 : 인스턴스 존재 상황에서 참조
Consumer<T> void accept(T t)
class JustSort {
public void sort(List<?> lst) { // 인스턴스 메소드
Collections.reverse(lst);
}
}
class ArrangeList3 {
public static void main(String[] args) {
List<Integer> ls = Arrays.asList(1, 3, 5, 7, 9);
ls = new ArrayList<>(ls);
JustSort js = new JustSort(); // js는 effective final - js 새로운 인스턴스 참조하면 컴파일 오류 뜸!!
Consumer<List<Integer>> c = e -> js.sort(e); // 람다식 기반
→ Consumer<List<Integer>> c = js::sort;
. . .
}
}
void accept(T t)
void sort(List<?> list)
accept로 전달된 것 sort로 그대로. . .
[9, 7, 5, 3, 1]
인스턴스 메소드 참조 1 : forEach 메소드
Consumer<T> void accept(T t)
class ForEachDemo {
public static void main(String[] args) {
List<String> ls = Arrays.asList("Box", "Robot");
ls.forEach(s -> System.out.println(s)); // 람다식 기반
ls.forEach(System.out::println); // 메소드 참조 기반
}
}
Consumer<? super T> action = System.out::println
accept로 전달된 것 그대로 println으로. . .
default void forEach(Consumer<? super T> action) { // Iterable<T>의 디폴트 메소드
for (T t : this) // this는 이 메소드가 속한 컬렉션 인스턴스를 의미함
action.accept(t); // 모든 저장된 데이터들에 대해 이 문장 반복
}
Box
Robot
Box
Robot
인스턴스 메소드 참조 2 : 인스턴스 없이 인스턴스 메소드 참조
ToIntBiFunction<T,U> int applyAsInt(T t, U u)
class IBox {
private int n;
public IBox(int i) { n = i; }
public int larger(IBox b) {
if(n > b.n)
return n;
else
return b.n;
}
}
public static void main(String[] args) {
IBox ib1 = new IBox(5);
IBox ib2 = new IBox(7);
// 두 상자에 저장된 값 비교하여 더 큰 값 반환
ToIntBiFunction<IBox, IBox> bf = (b1, b2) -> b1.larger(b2);
int bigNum = bf.applyAsInt(ib1, ib2);
System.out.println(bigNum);
}
// ToIntBiFunction<T, U> int applyAsInt(T t, U u)
ToIntBiFunction<IBox, IBox> bf = IBox::larger;
약속에 근거한 줄인 표현
생성자 참조
람다식을 작성 시 인스턴스 생성 후 이의 참조 값을 반환하는 경우가 있다.
이 경우 메소드 참조 방식을 쓸 수 있음.class StringMaker {
public static void main(String[] args) {
Function<char[], String> f = ar -> {
return new String(ar);
};
char[] src = {'R', 'o', 'b', 'o', 't'};
String str = f.apply(src);
System.out.println(str);
}
}
// Function<T, R> R apply(T t)
Function<char[], String> f = ar -> {
return new String(ar);
};
->
Function<char[], String> f = ar -> new String(ar);
->
Function<char[], String> f = String::new;
'# 02 > Java' 카테고리의 다른 글
[윤성우 열혈자바] 28-3. OptionalInt, OptionalLong, OptionalDouble 클래스 (0) | 2019.10.28 |
---|---|
[윤성우 열혈자바] 28-2. Optional 클래스 (0) | 2019.10.28 |
[윤성우 열혈자바] 27-2. 정의되어 있는 함수형 인터페이스 (0) | 2019.10.25 |
[윤성우 열혈자바] 27-1. 람다와 함수형 인터페이스 (0) | 2019.10.25 |
[윤성우 열혈자바] 26-2. 람다의 소개 (0) | 2019.10.25 |