方法引用
在使用Lambda表達(dá)式的時(shí)候,我們實(shí)際上傳遞進(jìn)去的代碼就是一種解決方案:拿什么參數(shù)做什么操作辐马。但是如果我們?cè)贚ambda中所指定的操作方案定血,已經(jīng)有地方存在相同方案,那就沒有必要再寫重復(fù)邏輯蔫仙。
用方法引用改進(jìn)Lambda代碼
//定義一個(gè)方法,參數(shù)傳遞Printable接口,對(duì)字符串進(jìn)行打印
public static void printString(Printable p) {
p.print("HelloWorld");
}
public static void main(String[] args) {
//調(diào)用printString方法,方法的參數(shù)Printable是一個(gè)函數(shù)式接口,所以可以傳遞Lambda
printString((s) -> {
System.out.println(s);
});
分析:
Lambda表達(dá)式的目的,打印參數(shù)傳遞的字符串
把參數(shù)s,傳遞給了System.out對(duì)象,調(diào)用out對(duì)象中的方法println對(duì)字符串進(jìn)行了輸出
注意:
1.System.out對(duì)象是已經(jīng)存在的
2.println方法也是已經(jīng)存在的
所以我們可以使用方法引用來(lái)優(yōu)化Lambda表達(dá)式
可以使用System.out方法直接引用(調(diào)用)println方法
printString(System.out::println);
}
方法引用符
雙冒號(hào):: 為引用運(yùn)算符,而它所在的表達(dá)式被稱為方法引用丐箩。如果Lambda要表達(dá)的函數(shù)方案已經(jīng)存在于某個(gè)方 法的實(shí)現(xiàn)中摇邦,那么則可以通過(guò)雙冒號(hào)來(lái)引用該方法作為L(zhǎng)ambda的替代者。
例如: System.out 對(duì)象中有一個(gè)重載的 println(String) 方法恰好就是我們所需要的屎勘。那么對(duì)于 printString 方法的函數(shù)式接口參數(shù)施籍,對(duì)比下面兩種寫法,完全等效:
- Lambda表達(dá)式寫法: s -> System.out.println(s);
- 方法引用寫法: System.out::println
第一種語(yǔ)義是指:拿到參數(shù)之后經(jīng)Lambda之手概漱,繼而傳遞給 System.out.println 方法去處理丑慎。 第二種等效寫法的語(yǔ)義是指:直接讓 System.out 中的 println 方法來(lái)取代Lambda。兩種寫法的執(zhí)行效果完全一 樣瓤摧,而第二種方法引用的寫法復(fù)用了已有方案立哑,更加簡(jiǎn)潔。
注:Lambda 中 傳遞的參數(shù) 一定是方法引用中 的那個(gè)方法可以接收的類型,否則會(huì)拋出異常
通過(guò)對(duì)象名引用成員方法
通過(guò)對(duì)象名引用成員方法
使用前提是對(duì)象名是已經(jīng)存在的,成員方法也是已經(jīng)存在
就可以使用對(duì)象名來(lái)引用成員方法
如果一個(gè)類中已經(jīng)存在了一個(gè)成員方法:
public class MethodRerObject {
//定義一個(gè)成員方法,傳遞字符串,把字符串按照大寫輸出
public void printUpperCaseString(String str){
System.out.println(str.toUpperCase());
}
}
函數(shù)式接口定義為:
@FunctionalInterface
public interface Printable {
//定義字符串的抽象方法
void print(String s);
}
通過(guò)對(duì)象名引用成員方法的實(shí)例:
//定義一個(gè)方法,方法的參數(shù)傳遞Printable接口
public static void printString(Printable p){
p.print("Hello");
}
public static void main(String[] args) {
//調(diào)用printString方法,方法的參數(shù)Printable是一個(gè)函數(shù)式接口,所以可以傳遞Lambda表達(dá)式
printString((s)->{
//創(chuàng)建MethodRerObject對(duì)象
MethodRerObject obj = new MethodRerObject();
//調(diào)用MethodRerObject對(duì)象中的成員方法printUpperCaseString,把字符串按照大寫輸出
obj.printUpperCaseString(s);
});
使用方法引用優(yōu)化Lambda
對(duì)象是已經(jīng)存在的MethodRerObject
成員方法也是已經(jīng)存在的printUpperCaseString
所以我們可以使用對(duì)象名引用成員方法
//創(chuàng)建MethodRerObject對(duì)象
MethodRerObject obj = new MethodRerObject();
printString(obj::printUpperCaseString);
}
通過(guò)類名稱引用靜態(tài)方法
通過(guò)類名引用靜態(tài)成員方法
類已經(jīng)存在,靜態(tài)成員方法也已經(jīng)存在
就可以通過(guò)類名直接引用靜態(tài)成員方法
通過(guò)類名稱引用靜態(tài)方法實(shí)例:
//定義一個(gè)方法,方法的參數(shù)傳遞要計(jì)算絕對(duì)值的整數(shù),和函數(shù)式接口Calcable
public static int method(int number,Calcable c){
return c.calsAbs(number);
}
public static void main(String[] args) {
//調(diào)用method方法,傳遞計(jì)算絕對(duì)值得整數(shù),和Lambda表達(dá)式
int number = method(-10,(n)->{
//對(duì)參數(shù)進(jìn)行絕對(duì)值得計(jì)算并返回結(jié)果
return Math.abs(n);
});
System.out.println(number);
使用方法引用優(yōu)化Lambda表達(dá)式
Math類是存在的
abs計(jì)算絕對(duì)值的靜態(tài)方法也是已經(jīng)存在的
所以我們可以直接通過(guò)類名引用靜態(tài)方法
int number2 = method(-10,Math::abs);
System.out.println(number2);
}
通過(guò)super引用成員方法
使用super引用類的成員方法
super是已經(jīng)存在的
父類的成員方法也是已經(jīng)存在的
所以我們可以直接使用super引用父類的成員方法
public class Man extends Human{
//子類重寫父類sayHello的方法
@Override
public void sayHello() {
System.out.println("Hello 我是Man!");
}
//定義一個(gè)方法參數(shù)傳遞Greetable接口
public void method(Greetable g){
g.greet();
}
public void show(){
//調(diào)用method方法,方法的參數(shù)Greetable是一個(gè)函數(shù)式接口,所以可以傳遞Lambda
method(()->{
//創(chuàng)建父類Human對(duì)象
Human h = new Human();
//調(diào)用父類的sayHello方法
h.sayHello();
});
//因?yàn)橛凶痈割愱P(guān)系,所以存在的一個(gè)關(guān)鍵字super,代表父類,所以我們可以直接使用super調(diào)用父類的成員方法
method(()->{
super.sayHello();
});
使用super引用類的成員方法
super是已經(jīng)存在的
父類的成員方法sayHello也是已經(jīng)存在的
所以我們可以直接使用super引用父類的成員方法
method(super::sayHello);
}
public static void main(String[] args) {
new Man().show();
}
}
通過(guò)this引用成員方法
通過(guò)this引用成員方法
this是已經(jīng)存在的
本類的成員方法也是已經(jīng)存在的
所以我們可以直接使用this引用本類的成員方法
public class Husband {
//定義一個(gè)買房子的方法
public void buyHouse(){
System.out.println("北京二環(huán)內(nèi)買一套四合院!");
}
//定義一個(gè)結(jié)婚的方法,參數(shù)傳遞Richable接口
public void marry(Richable r){
r.buy();
}
//定義一個(gè)非常高興的方法
public void soHappy(){
//調(diào)用結(jié)婚的方法,方法的參數(shù)Richable是一個(gè)函數(shù)式接口,傳遞Lambda表達(dá)式
marry(()->{
//使用this.成員方法,調(diào)用本類買房子的方法
this.buyHouse();
});
使用方法引用優(yōu)化Lambda表達(dá)式
this是已經(jīng)存在的
本類的成員方法buyHouse也是已經(jīng)存在的
所以我們可以直接使用this引用本類的成員方法buyHouse
marry(this::buyHouse);
}
public static void main(String[] args) {
new Husband().soHappy();
}
}
類的構(gòu)造器引用
類的構(gòu)造器(構(gòu)造方法)引用
構(gòu)造方法new Person(String name) 已知
創(chuàng)建對(duì)象已知 new
就可以使用Person引用new創(chuàng)建對(duì)象
類的構(gòu)造器(構(gòu)造方法)引用實(shí)例:
//定義一個(gè)方法,參數(shù)傳遞姓名和PersonBuilder接口,方法中通過(guò)姓名創(chuàng)建Person對(duì)象
public static void printName(String name,PersonBuilder pb){
Person person = pb.builderPerson(name);
System.out.println(person.getName());
}
public static void main(String[] args) {
//調(diào)用printName方法,方法的參數(shù)PersonBuilder接口是一個(gè)函數(shù)式接口,可以傳遞Lambda
printName("迪麗熱巴",(String name)->{
return new Person(name);
});
使用方法引用優(yōu)化Lambda表達(dá)式
構(gòu)造方法new Person(String name) 已知
創(chuàng)建對(duì)象已知 new
就可以使用Person引用new創(chuàng)建對(duì)象
printName("古力娜扎",Person::new);//使用Person類的帶參構(gòu)造方法,通過(guò)傳遞的姓名創(chuàng)建對(duì)象
}
數(shù)組的構(gòu)造器引用
定義一個(gè)創(chuàng)建數(shù)組的函數(shù)式接口
@FunctionalInterface
public interface ArrayBuilder {
//定義一個(gè)創(chuàng)建int類型數(shù)組的方法,參數(shù)傳遞數(shù)組的長(zhǎng)度,返回創(chuàng)建好的int類型數(shù)組
int[] builderArray(int length);
}
數(shù)組的構(gòu)造器引用實(shí)例:
定義一個(gè)方法
方法的參數(shù)傳遞創(chuàng)建數(shù)組的長(zhǎng)度和ArrayBuilder接口
方法內(nèi)部根據(jù)傳遞的長(zhǎng)度使用ArrayBuilder中的方法創(chuàng)建數(shù)組并返回
public static int[] createArray(int length, ArrayBuilder ab){
return ab.builderArray(length);
}
public static void main(String[] args) {
//調(diào)用createArray方法,傳遞數(shù)組的長(zhǎng)度和Lambda表達(dá)式
int[] arr1 = createArray(10,(len)->{
//根據(jù)數(shù)組的長(zhǎng)度,創(chuàng)建數(shù)組并返回
return new int[len];
});
System.out.println(arr1.length);//10
使用方法引用優(yōu)化Lambda表達(dá)式
已知?jiǎng)?chuàng)建的就是int[]數(shù)組
數(shù)組的長(zhǎng)度也是已知的
就可以使用方法引用
int[]引用new,根據(jù)參數(shù)傳遞的長(zhǎng)度來(lái)創(chuàng)建數(shù)組
int[] arr2 =createArray(10,int[]::new);
System.out.println(Arrays.toString(arr2));
System.out.println(arr2.length);//10