方法引用就是通過類名或方法名引用已經存在的方法來簡化lambda表示式。那麼什麼時候需要用方法引用呢?如果lamdba體中的內容已經有方法實現了,我們就可以使用方法引用。
一、方法引用的三種語法格式
1. 物件::例項方法名
lamdba寫法:
@Test
void test1(){
Consumer<String> con = x -> System.out.println(x);
}
方法引用寫法:
@Test
void test2(){
PrintStream out = System.out;
Consumer<String> con = out::println;
}
consumer介面:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
注意:被呼叫的方法的引數列表和返回值型別需要與函式式介面中抽象方法的引數列表和返回值型別要一致。
2. 類::靜態方法名
lamdba寫法:
@Test
void test3(){
Comparator<Integer> com = (x, y) -> Integer.compare(x,y);
}
方法引用寫法:
@Test
void test4(){
Comparator<Integer> com = Integer::compare;
}
Comparator介面:
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Integer類部分內容:
public final class Integer extends Number implements Comparable<Integer> {
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
}
注意:被呼叫的方法的引數列表和返回值型別需要與函式式介面中抽象方法的引數列表和返回值型別要一致。
3. 類::例項方法名
lamdba寫法:
@Test
void test5(){
BiPredicate<String,String> bp = (x,y) -> x.equals(y);
}
方法引用寫法:
@Test
void test6(){
BiPredicate<String,String> bp = String::equals;
}
BiPredicate介面:
@FunctionalInterface
public interface BiPredicate<T, U> {
boolean test(T t, U u);
}
注意:第一個引數是這個例項方法的呼叫者,第二個引數是這個例項方法的引數時,就可以使用這種語法。
二、構造器引用
類::new
lamdba寫法:
@Test
void test7(){
Supplier<Person> supplier = ()->new Person();
}
構造器引用寫法:
@Test
void test8(){
Supplier<Person> supplier = Person::new;
}
Supplier介面:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Person類:
@Data
public class Person implements Serializable {
private static final long serialVersionUID = -7008474395345458049L;
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
注意:person類中有兩個構造器,要呼叫哪個構造器是函式式介面決定的,也就是Supplier介面中的get()方法是無參的,那麼就呼叫的是person中的無參構造器。
三、陣列引用
Type::new
lamdba寫法:
@Test
void test9(){
Function<Integer,String[]> fun = x -> new String[x];
}
陣列引用寫法:
@Test
void test10(){
Function<Integer, String[]> fun = String[]::new;
}
Function介面部分內容:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
總結
- 方法應用及構造器引用其實可以理解為lamdba的另一種表現形式
- 方法引用被呼叫的方法的引數列表和返回值型別需要與函式式介面中抽象方法的引數列表和返回值型別要一致
- 方法引用中使用類::例項方法的條件是第一個引數是這個例項方法的呼叫者,第二個引數是這個例項方法的引數
- 構造器引用需要呼叫的構造器的引數列表要與函式式介面中抽象方法的引數列表一致