- 在使用Lambda表達式的時候喘落,我們實際上傳遞進去的代碼就是一種解決方案:拿什么參數(shù)做什么操作。那么考慮一種情況:如果我們在Lambda中所指定的操作方案蟹倾,已經有地方存在相同方案匣缘,那是否還有必要再寫重復邏輯?
- 用方法引用改進Lambda表達式鲜棠,雙冒號 :: 寫法肌厨,這被稱為“方法引用”,而雙冒號是一種新的語法豁陆。
- 如果Lambda要表達的函數(shù)方案已經存在于某個方法的實現(xiàn)中柑爸,那么則可以通過雙冒號來引用該方法作為Lambda的替代者。
public class Demo01Printable {
//定義一個方法,參數(shù)傳遞Printable接口,對字符串進行打印
public static void printString(Printable p) {
p.print("HelloWorld");
}
public static void main(String[] args) {
//調用printString方法,方法的參數(shù)Printable是一個函數(shù)式接口,所以可以傳遞Lambda
printString((s) -> {
System.out.println(s);
});
/*
分析:
Lambda表達式的目的,打印參數(shù)傳遞的字符串
把參數(shù)s,傳遞給了System.out對象,調用out對象中的方法println對字符串進行了輸出
注意:
1.System.out對象是已經存在的
2.println方法也是已經存在的
所以我們可以使用方法引用來優(yōu)化Lambda表達式
可以使用System.out方法直接引用(調用)println方法
*/
printString(System.out::println);
}
}
/*
定義一個打印的函數(shù)式接口
*/
@FunctionalInterface
public interface Printable {
//定義字符串的抽象方法
void print(String s);
}
1. 通過對象名引用成員方法
/*
通過對象名引用成員方法
使用前提是對象名是已經存在的,成員方法也是已經存在
就可以使用對象名來引用成員方法
*/
public class Demo01ObjectMethodReference {
//定義一個方法,方法的參數(shù)傳遞Printable接口
public static void printString(Printable p){
p.print("Hello");
}
public static void main(String[] args) {
//調用printString方法,方法的參數(shù)Printable是一個函數(shù)式接口,所以可以傳遞Lambda表達式
printString((s)->{
//創(chuàng)建MethodRerObject對象
MethodRerObject obj = new MethodRerObject();
//調用MethodRerObject對象中的成員方法printUpperCaseString,把字符串按照大寫輸出
obj.printUpperCaseString(s);
});
/*
使用方法引用優(yōu)化Lambda
對象是已經存在的MethodRerObject
成員方法也是已經存在的printUpperCaseString
所以我們可以使用對象名引用成員方法
*/
//創(chuàng)建MethodRerObject對象
MethodRerObject obj = new MethodRerObject();
printString(obj::printUpperCaseString);
}
}
public class MethodRerObject {
//定義一個成員方法,傳遞字符串,把字符串按照大寫輸出
public void printUpperCaseString(String str){
System.out.println(str.toUpperCase());
}
}
/*
定義一個打印的函數(shù)式接口
*/
@FunctionalInterface
public interface Printable {
//定義字符串的抽象方法
void print(String s);
}
2. 通過類名稱引用靜態(tài)方法
@FunctionalInterface
public interface Calcable {
//定義一個抽象方法,傳遞一個整數(shù),對整數(shù)進行絕對值計算并返回
int calsAbs(int number);
}
/*
通過類名引用靜態(tài)成員方法
類已經存在,靜態(tài)成員方法也已經存在
就可以通過類名直接引用靜態(tài)成員方法
*/
public class Demo01StaticMethodReference {
//定義一個方法,方法的參數(shù)傳遞要計算絕對值的整數(shù),和函數(shù)式接口Calcable
public static int method(int number,Calcable c){
return c.calsAbs(number);
}
public static void main(String[] args) {
//調用method方法,傳遞計算絕對值得整數(shù),和Lambda表達式
int number = method(-10,(n)->{
//對參數(shù)進行絕對值得計算并返回結果
return Math.abs(n);
});
System.out.println(number);
/*
使用方法引用優(yōu)化Lambda表達式
Math類是存在的
abs計算絕對值的靜態(tài)方法也是已經存在的
所以我們可以直接通過類名引用靜態(tài)方法
*/
int number2 = method(-10,Math::abs);
System.out.println(number2);
}
}
3. 通過super引用成員方法
/*
定義父類
*/
public class Human {
//定義一個sayHello的方法
public void sayHello(){
System.out.println("Hello 我是Human!");
}
}
/*
定義子類
*/
public class Man extends Human{
//子類重寫父類sayHello的方法
@Override
public void sayHello() {
System.out.println("Hello 我是Man!");
}
//定義一個方法參數(shù)傳遞Greetable接口
public void method(Greetable g){
g.greet();
}
public void show(){
//調用method方法,方法的參數(shù)Greetable是一個函數(shù)式接口,所以可以傳遞Lambda
/*method(()->{
//創(chuàng)建父類Human對象
Human h = new Human();
//調用父類的sayHello方法
h.sayHello();
});*/
//因為有子父類關系,所以存在的一個關鍵字super,代表父類,所以我們可以直接使用super調用父類的成員方法
/* method(()->{
super.sayHello();
});*/
/*
使用super引用類的成員方法
super是已經存在的
父類的成員方法sayHello也是已經存在的
所以我們可以直接使用super引用父類的成員方法
*/
method(super::sayHello);
}
public static void main(String[] args) {
new Man().show();
}
}
/*
定義見面的函數(shù)式接口
*/
@FunctionalInterface
public interface Greetable {
//定義一個見面的方法
void greet();
}
4. 通過this引用成員方法
/*
定義一個富有的函數(shù)式接口
*/
@FunctionalInterface
public interface Richable {
//定義一個想買什么就買什么的方法
void buy();
}
/*
使用this引用本類的成員方法
*/
public class Husband {
//定義一個買房子的方法
public void buyHouse(){
System.out.println("北京二環(huán)內買一套四合院!");
}
//定義一個結婚的方法,參數(shù)傳遞Richable接口
public void marry(Richable r){
r.buy();
}
//定義一個非常高興的方法
public void soHappy(){
//調用結婚的方法,方法的參數(shù)Richable是一個函數(shù)式接口,傳遞Lambda表達式
/* marry(()->{
//使用this.成員方法,調用本類買房子的方法
this.buyHouse();
});*/
/*
使用方法引用優(yōu)化Lambda表達式
this是已經存在的
本類的成員方法buyHouse也是已經存在的
所以我們可以直接使用this引用本類的成員方法buyHouse
*/
marry(this::buyHouse);
}
public static void main(String[] args) {
new Husband().soHappy();
}
}
5. 類的構造器引用
/*
定義一個創(chuàng)建Person對象的函數(shù)式接口
*/
@FunctionalInterface
public interface PersonBuilder {
//定義一個方法,根據(jù)傳遞的姓名,創(chuàng)建Person對象返回
Person builderPerson(String name);
}
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
類的構造器(構造方法)引用
*/
public class Demo {
//定義一個方法,參數(shù)傳遞姓名和PersonBuilder接口,方法中通過姓名創(chuàng)建Person對象
public static void printName(String name,PersonBuilder pb){
Person person = pb.builderPerson(name);
System.out.println(person.getName());
}
public static void main(String[] args) {
//調用printName方法,方法的參數(shù)PersonBuilder接口是一個函數(shù)式接口,可以傳遞Lambda
printName("迪麗熱巴",(String name)->{
return new Person(name);
});
/*
使用方法引用優(yōu)化Lambda表達式
構造方法new Person(String name) 已知
創(chuàng)建對象已知 new
就可以使用Person引用new創(chuàng)建對象
*/
printName("古力娜扎",Person::new);//使用Person類的帶參構造方法,通過傳遞的姓名創(chuàng)建對象
}
}
6. 數(shù)組的構造器引用
/*
數(shù)組的構造器引用
*/
public class Demo {
/*
定義一個方法
方法的參數(shù)傳遞創(chuàng)建數(shù)組的長度和ArrayBuilder接口
方法內部根據(jù)傳遞的長度使用ArrayBuilder中的方法創(chuàng)建數(shù)組并返回
*/
public static int[] createArray(int length, ArrayBuilder ab){
return ab.builderArray(length);
}
public static void main(String[] args) {
//調用createArray方法,傳遞數(shù)組的長度和Lambda表達式
int[] arr1 = createArray(10,(len)->{
//根據(jù)數(shù)組的長度,創(chuàng)建數(shù)組并返回
return new int[len];
});
System.out.println(arr1.length);//10
/*
使用方法引用優(yōu)化Lambda表達式
已知創(chuàng)建的就是int[]數(shù)組
數(shù)組的長度也是已知的
就可以使用方法引用
int[]引用new,根據(jù)參數(shù)傳遞的長度來創(chuàng)建數(shù)組
*/
int[] arr2 =createArray(10,int[]::new);
System.out.println(Arrays.toString(arr2));
System.out.println(arr2.length);//10
}
}
/*
定義一個創(chuàng)建數(shù)組的函數(shù)式接口
*/
@FunctionalInterface
public interface ArrayBuilder {
//定義一個創(chuàng)建int類型數(shù)組的方法,參數(shù)傳遞數(shù)組的長度,返回創(chuàng)建好的int類型數(shù)組
int[] builderArray(int length);
}