Lambd
JAVA技術交流群:737698533
lambda表達式是java8的新特性,可以使用函數式接口替換掉原來的匿名內部類
lambda的本質就是引用一個已經具體實現的方法來完成對函數式接口抽象方法的具體實現
例如現在有一個接口,里面只有一個求和方法
public interface Mylambda {
int sum(int a,int b);
}
我們現在想要使用這個方法,有三種方式
- 創建一個類實現這個接口
- 匿名內部類
- 使用lambda函數式接口
第一種方法就不說了,來看使用匿名內部類
Mylambda myLambda=new Mylambda() {
@Override
public int sum(int a, int b) {
return a+b;
}
};
然后調用myLambda的sum方法可以做到求和的操作
再來看看lambda
Mylambda myLambda=(int a,int b)->{
return a+b;
};
()->{} 什么意思呢? 我們來看看lambda是如何使用的
()
里面是傳入的參數
{}
里面為方法體具體操作
需要注意的點
- lambda只能用於只有一個方法的接口
- 最好在接口上添加注解
@FunctionalInterface
來表明這是一個函數式接口 - 參數類型因為已經在接口中定義,那么傳入參數時可以不用寫參數類型,要么參數都寫參數類型,要不然都不寫參數類型
- 參數的數量,類型,順序必須和接口中一致
那么lambda就這些嗎? 當然不是,還可以簡化以及拆分方法
簡化
如果方法體中就只有一條return語句,例如上面sum方法中,那么在lambda表達式中可以省略大括號以及return
public static void main(String[] args) {
Mylambda mylambda = (a,b) -> a + b;
}
如果參數只有一個,可以省略小括號
例如下面這個接口,我們並沒有做任何操作,只是將傳入參數原封不動返回,只是為了學習使用
@FunctionalInterface
public interface MyLambda2 {
int print(int i);
}
使用
public static void main(String[] args) {
MyLambda2 myLambda2= i -> i;
}
是不是看的有點蒙呢,不簡化就是
MyLambda2 myLambda2= (i) -> {
return i;
};
因為參數只有一個,而且返回值也只有一條return語句,所以省略了傳入參數的小括號以及方法體的大括號和return關鍵字
這里也有個需要注意的點 : 方法體的大括號和return語句要么都省略,不能只省略一個
如果方法中僅僅想返回一個對象,不做任何其他操作,還可以簡化
//接口============
@FunctionalInterface
public interface MyLambda2 {
User getUser();
}
//使用,未簡化前===========
public static void main(String[] args) {
MyLambda2 myLambda=()->{
return new User();
};
}
//再根據參數和方法體簡化=====
public static void main(String[] args) {
MyLambda2 myLambda2=()->new User();
}
//使用,簡化后
public static void main(String[] args) {
MyLambda2 myLambda=User::new;
}
上面兩個使用估計都可以看懂,但是最后一個User::new
估計有點蒙,什么意思呢?
在開頭就講過 lambda的本質就是引用一個已經具體實現的方法來完成對函數式接口抽象方法的具體實現
而lambda創建User對象說白了就是調用User的構造方法,而lambda調用對象的構造方法的語法就是 類型::new
也就是上面寫的User::new,這種方式稱為構造器引用
那么如果想通過lambda調用對象的有參構造呢?
很遺憾,不能通過這種方式來調用對象的有參構造,如果想通過lambda調用,我們可以稍微簡化為下面這種
//接口========
@FunctionalInterface
public interface MyLambda2 {
User getUser(String name,int age);
}
//測試=============
public static void main(String[] args) {
MyLambda2 myLambda2=(name,age)->new User();
}
拆分,也就是方法引用
那么如果一個方法我們經常使用該怎么辦呢,難道每次都去復制原來的lambda表達式嗎?
可以將常用的方法單獨拆分出來,每次lambda表達式去調用這個方法即可
我們以上面的sum接口為例 :
//接口===================
@FunctionalInterface
public interface Mylambda {
int sum(int a,int b);
}
//測試==================
public static void main(String[] args) {
Mylambda mylambda = (a,b)-> doSum(a,b);
int sum = mylambda.sum(2, 5);
}
//抽取出的方法( 注意是靜態調用靜態,如果是普通方法需要創建對象 )===============
public static int doSum(int a,int b){
return a+b;
}
我們將求和的操作單獨拆分為一個方法,每次使用時只需要調用這個方法即可
() -> xxx();
也就是說lambda不僅可以直接寫方法具體細節,也可以調用其他方法,需要注意的時調用的方法返回值必須和接口定義返回值一致
當然,調用拆分的方法也可以簡化,使用方法如下
靜態類 類名::方法
非靜態 對象::方法
對於靜態的方法引用
//接口=======
@FunctionalInterface
public interface Mylambda {
int sum(int a,int b);
}
//測試類名為Test=========
public static void main(String[] args) {
Mylambda myLambda=Test::doSum;
}
//拆分的方法========
public static int doSum(int a,int b){
return a+b;
}
對於非靜態方法引用
//接口=======
@FunctionalInterface
public interface Mylambda {
int sum(int a,int b);
}
//測試類名為Test=========
public static void main(String[] args) {
Test test = new Test();
Mylambda myLambda=test::doSum;
}
//拆分的方法========
public static int doSum(int a,int b){
return a+b;
}
兩者區別僅僅是在於對象::方法和類::方法,因為非靜態類需要創建出對象才可以調用方法
當使用簡化后的調用方法那么會自動匹配參數類型,數量和順序,所以更加要嚴謹仔細,確保參數一一對應
再說一遍吧,lambda的本質就是引用一個已經具體實現的方法來完成對函數式接口抽象方法的具體實現,那么現在再來看這句話是不是清楚很多呢
本文僅個人理解,如果有不對的地方歡迎評論指出或私信,謝謝٩(๑>◡<๑)۶