Java8-Lambda表達式

Lambd

lambda表達式是java8的新特性,可使用函數式接口替換掉原來的匿名內部類java

lambda的本質就是引用一個已經具體實現的方法來完成對函數式接口抽象方法的具體實現ide

例如如今有一個接口,裏面只有一個求和方法函數

public interface Mylambda {
    int sum(int a,int b);
}

咱們如今想要使用這個方法,有三種方式學習

  1. 建立一個類實現這個接口
  2. 匿名內部類
  3. 使用lambda函數式接口

第一種方法就不說了,來看使用匿名內部類測試

Mylambda myLambda=new Mylambda() {
    @Override
    public int sum(int a, int b) {
        return a+b;
    }
};

而後調用myLambda的sum方法能夠作到求和的操做code

再來看看lambda對象

Mylambda myLambda=(int a,int b)->{
    return a+b;
};

()->{} 什麼意思呢? 咱們來看看lambda是如何使用的接口

() 裏面是傳入的參數get

{} 裏面爲方法體具體操做io

須要注意的點

  1. lambda只能用於只有一個方法的接口
  2. 最好在接口上添加註解@FunctionalInterface來代表這是一個函數式接口
  3. 參數類型由於已經在接口中定義,那麼傳入參數時能夠不用寫參數類型,要麼參數都寫參數類型,要否則都不寫參數類型
  4. 參數的數量,類型,順序必須和接口中一致

那麼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的本質就是引用一個已經具體實現的方法來完成對函數式接口抽象方法的具體實現,那麼如今再來看這句話是否是清楚不少呢

本文僅我的理解,若是有不對的地方歡迎評論指出或私信,謝謝٩(๑>◡<๑)۶

相關文章
相關標籤/搜索