方法引用:
創建了函數式接口的匿名內部類對象
重寫了函數式接口的抽象方法並在重寫的方法中調用被引用的方法
通俗的說,就是用lambda創建了函數式接口的實現類對象,正好lambda要寫的抽象體是其他方法的方法體
1.靜態方法引用
格式 :
類名::方法名
注意事項:
被引用的方法參數列表和函數式接口中抽象方法的參數一致!!
接口的抽象方法沒有返回值,引用的方法可以有返回值也可以沒有
接口的抽象方法有返回值,引用的方法必須有相同類型的返回值!!
interface test {
public void run(String string);
}
public class blog {
public static void main(String[] args) {
printString("靜態方法引用",System.out::println);
// 實質代碼: printString("靜態方法引用", (string) -> System.out.println(string));
}
public static void printString(String str, test t) {
t.run(str);
}
}
這個代碼中,利用lambda表達式創建了test接口的實現類對象,
重寫run()方法,正好方法體是靜態方法printString方法
稍微修改一下,將函數式接口抽象方法作爲一個有返回值的方法,那麼引用方法也得有同樣類型的返回值
interface test {
public int run(String string);
}
public class blog {
public static void main(String[] args) {
// 實質代碼: getInteger("123", (str) -> Integer.parseInt(str));
int i = getInteger("123", Integer::parseInt);
System.out.println(i); //輸出:123
}
public static int getInteger(String str, test t) {
return t.run(str);
}
}
兩個例子中,分別調用System.out類的println靜態方法,Integer類的parseInt靜態方法
由於滿足抽象參數列表與引用參數列表相同,所以可以寫成靜態方法引用的格式
2.對象方法引用
格式:
對象名::非靜態方法名
注意事項與靜態方法引用完全一致
@FunctionalInterface
interface test {
public String run(String string);
}
class Person {
public String goWalking(String string) {
return string.concat(" 引用方法");
}
}
public class blog {
public static void main(String[] args) {
//實質代碼: test t1 = (string) -> new Person().goWalking(string);
//實質代碼: System.out.println(t1.run("對象"));
test t2 = new Person()::goWalking;
System.out.println(t2.run("對象")); //輸出:對象 引用方法
}
}
類中有一個方法goWalking()方法體是test實現類對象需要的方法體
且方法列表參數一致,返回值類型相同
則可以利用lambda創建test的實現類對象,然後重寫的抽象方法體就是調用Person對象的goWalking方法
符合對象引用方法的所有要求,則可以寫成t2的樣式
3.構造方法引用
格式:
類名::new
注意事項:
被引用的類必須存在一個構造方法與函數式接口的抽象方法參數列表一致
interface test {
public Person1 run(String string);
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
public class blog {
public static void main(String[] args) {
//實質代碼: test t1 = (string) -> new Person(string);
//實質代碼: Person p = t1.run("張三");
test t2 = Person::new;
Person p2 = t2.run("李四");
System.out.println(p2); //輸出:Person{name='李四'}
}
}
由於函數式接口test中抽象方法,返回值是Person對象,且參數列表與Person類中的構造方法相同
則可以通過創建函數式接口的實現類對象,方法體通過調用類中的構造方法創建對象
使用了構造方法引用寫成了代碼中t2的形式
4.數組構造方法引用
格式:
數據類型[ ]::new
interface test {
public String[] run(int length);
}
public class blog {
public static void main(String[] args) {
//實質代碼: test t1 = (length) -> new String[length];
test t2 = String[]::new;
String[] arr = t2.run(5);
}
}
5.特定類型的方法引用
格式:
類名::非靜態方法
public class blog {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"d1wdaddq","ASDINAOSDN","aa","AA");
//實質代碼: Collections.sort(list,(string1,string2)->string1.compareToIgnoreCase(string2));
Collections.sort(list,String::compareToIgnoreCase);
System.out.println(list);
}
}
特定類型方法引用,在Comparator函數式接口的抽象方法中傳入的參數有兩個,
可是compareToIgnoreCase()方法參數只有一個,第一個傳入的參數作調用對象
這就滿足了特定類型的方法引用,所以可以簡化成類名::非靜態方法的形式
6.類中方法調用父類或本類方法引用
格式:
this::方法名
super::方法名
interface test {
public void itMethod();
}
class father {
public void buy() {
System.out.println("買東西");
}
}
class son extends father {
public void buy() {
System.out.println("買糖");
}
public void test() {
// 實質代碼: test t = () -> buy();
test t = this::buy;
t.itMethod();
// 實質代碼: test t2 = ()->super.buy();
test t2 = super::buy;
t2.itMethod();
}
}
public class blog {
public static void main(String[] args) {
son s = new son();
s.test(); //輸出: 買糖 買東西
}
}
在有繼承關係的類中,若方法想調用本類或父類的成員方法
在函數式接口抽象方法與成員方法參數列表相同,且返回值類型相同的情況下
也可以使用this和super的方法引用來簡寫原本的lambda代碼
————————————————
版權聲明:本文爲CSDN博主「cikinn」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_42022555/article/details/81943263