java8系列-01 Lambdas 表達式

image

Lambdas表達式是java 8的一個最重要的新特性燥狰。它允許把函數(shù)作為一個方法的參數(shù)(在一個方法中用函數(shù)來作為方法傳遞進去)科吭。或者把一段代碼看成是數(shù)據(jù)。

Lambdas表達式實例

基本語法如下:

(parameters) -> experssion
或
(parameters) -> {statements;}

舉栗說明

public class LombokTest {
    public static void main(String[] args) {
        // 簡單情況下不用return
        Arrays.asList("a","b","c").forEach(System.out::println);
        // 復雜情況下可以帶對花括號派近,像java代碼塊一樣
        Arrays.asList("d","e","f").sort((e1,e2) ->{
                int res = e1.compareTo(e2);
                return res;
        });
        // runoob例子==類型聲明
        MathOperation sub = (int a,int b) -> a - b;
        // runoob例子==不用類型聲明
        MathOperation add = (a,b) -> a+b;
        LombokTest lt = new LombokTest();
        System.out.println("1+2="+lt.operate(1,2,add));
        System.out.println("1-2="+lt.operate(1,2,sub));
    }

    interface MathOperation {
        int operation(int a, int b);
    }

    private int operate(int a, int b, MathOperation mathOperation){
        return mathOperation.operation(a, b);
    }
}

控制臺打印

a
b
c
1+2=3
1-2=-1

使用Lambdas表達式需要注意以下兩點

  • Lambda表達式主要用來定義行內(nèi)執(zhí)行的方法類型接口备畦。例如上面的MathOperation接口武通。
  • Lamda表達式免去了使用匿名方法的麻煩堪滨,并且給予java簡單但是強大的函數(shù)化的編程能力。

Lambdas表達式中的變量作用域

Lambdas表達式可以引用類的成員變量和局部變量蕾各。如果這些類型不是final的話扒磁,它們也會隱含的轉(zhuǎn)換成final

public class LombokTest {
    int a = 12;
    public static void main(String[] args) {
        // 引用成員變量
        LombokTest lt = new LombokTest();
        Converter<Integer,String> s = (param) -> System.out.println((param + lt.a));
        s.convert(8);
        // 引用局部變量
        String separator = ",";
        Arrays.asList("a","b","c").forEach((String e) -> System.out.print(e+separator));
        
        // 在 Lambda 表達式當中不允許聲明一個與局部變量同名的參數(shù)或者局部變量。
        String first = "1";
        Comparator<String> comparator = (first,second) 
                -> Integer.compare(first.length(),second.length());  // idea編譯報錯Variable 'first' is already defined in the scope
        // Lambda中this的應用
        lt.sayOk();
    }

    public String toString(){
        return "\n are u ok?";
    }

    private void sayOk(){
        Runnable runnable = () ->{
            System.out.println(this.toString());
        };
        new Thread(runnable).start();
    }
    private interface Converter<T1,T2>{
        void convert(int i);
        default void say() {
        }
    }
}

注釋掉報錯代碼后式曲,控制臺打印

20
a,b,c,
 are u ok?

NOTE

  • 和匿名對象有點不同的是妨托,Lambda表達式當中引用的變量可以不用聲明為final
  • Lambda表達式的字段類型為final缸榛,所以在后面的代碼中不能被修改。如例子中String separator = ",";后續(xù)代碼中如果修改為separator = "兰伤。";則會被編譯器報錯
  • Lambda表達式當中不允許聲明一個與局部變量重名的參數(shù)或者局部變量内颗。
  • 和局部變量不同的是,Lambda內(nèi)部對于實例的字段(即:成員變量)以及靜態(tài)變量是即可讀又可寫敦腔。
  • Lambda表達式中無法訪問到接口的默認方法(java 8新特性均澳,下面講到)。如上Converter接口的 say()是無法被訪問的符衔。
  • Lambda中的this會去引用創(chuàng)建該Lambda表達式的方法的this找前,如上are u ok?

接口的默認方法與靜態(tài)方法

接口的默認方法與靜態(tài)方法是java 8的新概念,用來擴展接口的聲明判族。與傳統(tǒng)接口不同躺盛,它可以在接口中添加方法。另外它并不受函數(shù)式接口(帶有注解@FunctionalInterface)的契約五嫂,可以任意使用颗品。

默認方法

默認方法用default關鍵詞修飾肯尺,可以在接口中存在多個沃缘。與接口抽象方法不同,它是一個非抽象的方法實現(xiàn)则吟。它的使用方式有點類似于抽象類中的非抽象成員方法槐臀。這個特征也叫擴展方法

==Warning:==
在實現(xiàn)默認方法時,它是<font color='red'>不能夠</font>重寫Object中的方法氓仲,但是可以重載Object 中的方法水慨。例如toStringhashCode等方法不能被覆蓋敬扛,但是卻可以被重載調(diào)用晰洒。

    interface DefaultM{
        default String myDefaultMothod(){
            return "https://code666.top";
        }
        // 因為重寫了Object方法,以下就會報錯
        default String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    }

    static class DefaultMM implements DefaultM{
        public void test(){
            System.out.println(myDefaultMothod());
        }
    }

    public static void main(String[] args) {
        DefaultMM dmm = new DefaultMM();
        dmm.test();
    }

靜態(tài)方法

靜態(tài)方法用static修飾啥箭,可以通過接口名調(diào)用谍珊。

  interface DefaultM2{
        static DefaultM create(Supplier<DefaultM> supplier){
            return supplier.get();
        }
    }
    static class DefaultMM implements DefaultM{
        public void test(){
            System.out.println(myDefaultMothod());
        }
    }

    public static void main(String[] args) {
        DefaultM defaultM = DefaultM2.create(DefaultMM::new);
        System.out.println(defaultM.myDefaultMothod());
    }

總結(jié)

為什么接口的默認方法不能重載toString(),hashCode()和equals()?

接口不能提供對Object類的任何方法的默認實現(xiàn),因為若可以會很難確定什么時候該調(diào)用接口默認的方法急侥。并且也是毫無意義的砌滞。因為每一個java類都是Object的子類,也都繼承了它類中的equals等方法坏怪。

默認方法和靜態(tài)方法的注意點

  1. 接口默認方法贝润、靜態(tài)方法可以有多個。
  2. 默認方法通過實例調(diào)用铝宵,靜態(tài)方法通過接口名調(diào)用打掘。
  3. default默認方法關鍵字只能用在接口中。
  4. 默認方法可以被繼承,如果繼承了多個接口尊蚁,多個接口都定義了多個同樣的默認方法唯绍,實現(xiàn)類需要重寫默認方法不然會報錯。
  5. 靜態(tài)方法不能被繼承及覆蓋枝誊,所以只被具體所在的接口調(diào)用

函數(shù)式接口@FunctionalInterface

函數(shù)式接口(Functional Interface)就是一個有且僅有一個抽象方法况芒,但是可以有多個非抽象方法的接口。函數(shù)式接口可以被隱式轉(zhuǎn)換為 lambda 表達式叶撒。

定義如下

@FunctionalInterface
public interface Functional<T>{
    void test(T t);
}

Warnning:

  1. 該注解只能標記在有且只有抽象方法的接口上绝骚。若接口有兩個抽象方法則編譯器會報錯(上面提到的默認方法靜態(tài)方法都不是抽象方法)。
  2. 因為接口也是默認繼承java.lang.Object的祠够,所以如果重寫了Object內(nèi)的方法則也不屬于抽象方法压汪。
  3. 并且該注解不是必須的。如果一個接口符合‘函數(shù)式接口’規(guī)范,那加不加該注解都不影響古瓤,但是加了該注解后編譯器會校驗止剖。(==也就是說如果該接口是為了函數(shù)式接口而生的,就可以加上此注解==)

實例

接口還是上面那個落君。PS初級開發(fā): static <T> void<T>不是返回值穿香,表示傳入?yún)?shù)有泛型

public class FunctionalTest {

    private static <T> void Test(Functional<T> fun, T t){ 
        System.out.print("https://");
        fun.test(t);
        System.out.print(".top");
    }

    public static void main(String[] args) {
        String s = "code666";
        Test(System.out::print,s);
    }
}

輸出 https://code666.top

通過輸入和輸出的參數(shù)來區(qū)分,函數(shù)式接口有如下四類

接口名 說明 接口方法
Function<T,R> 接收一個T類型的參數(shù)绎速,返回一個R類型的結(jié)果 R apply(T t)
Consumer<T> 接收一個T類型的參數(shù)皮获,不返回結(jié)果 void accept(T t)
Predicate<T> 接收一個T類型的參數(shù),返回一個boolean類型的結(jié)果 boolean test(T t)
Supplier<T> 不接收參數(shù)纹冤,返回一個T類型的結(jié)果 T get()

接收兩個參數(shù)的相關函數(shù)式接口

接口名 說明
BiFunction<T,U,R> 接收T類型U類型兩參數(shù)洒宝,返回一個R類型結(jié)果
BiConsumer<T,U> 接收T類型U類型兩參數(shù)不返回值
BiPredicate<T,U> 接收T類型和U類型的兩個參數(shù),返回一個boolean類型的結(jié)果

總結(jié): 函數(shù)式接口就是只包含一個抽象方法的接口


覺得還行可以點個星星哦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萌京,一起剝皮案震驚了整個濱河市雁歌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌知残,老刑警劉巖靠瞎,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異橡庞,居然都是意外死亡较坛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門扒最,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丑勤,“玉大人,你說我怎么就攤上這事吧趣》ň海” “怎么了耙厚?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長岔霸。 經(jīng)常有香客問我薛躬,道長,這世上最難降的妖魔是什么呆细? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任型宝,我火速辦了婚禮,結(jié)果婚禮上絮爷,老公的妹妹穿的比我還像新娘趴酣。我一直安慰自己,他們只是感情好坑夯,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布岖寞。 她就那樣靜靜地躺著,像睡著了一般柜蜈。 火紅的嫁衣襯著肌膚如雪仗谆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天淑履,我揣著相機與錄音隶垮,去河邊找鬼。 笑死鳖谈,一個胖子當著我的面吹牛岁疼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缆娃,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瑰排!你這毒婦竟也來了贯要?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤椭住,失蹤者是張志新(化名)和其女友劉穎崇渗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體京郑,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡宅广,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了些举。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跟狱。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖户魏,靈堂內(nèi)的尸體忽然破棺而出驶臊,到底是詐尸還是另有隱情挪挤,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布关翎,位于F島的核電站扛门,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纵寝。R本人自食惡果不足惜论寨,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爽茴。 院中可真熱鬧政基,春花似錦、人聲如沸闹啦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窍奋。三九已至荐健,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間琳袄,已是汗流浹背江场。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窖逗,地道東北人址否。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像碎紊,于是被迫代替她去往敵國和親佑附。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前段時間一直在看lambda表達式仗考,但是總感覺吃不透音同,在深入了解lambda表達式的時候,需要很多基礎的知識棧秃嗜。這...
    西瓜真好吃丶閱讀 2,722評論 0 7
  • lambda表達式(又被成為“閉包”或“匿名方法”)方法引用和構(gòu)造方法引用擴展的目標類型和類型推導接口中的默認方法...
    183207efd207閱讀 1,473評論 0 5
  • 簡介 概念 Lambda 表達式可以理解為簡潔地表示可傳遞的匿名函數(shù)的一種方式:它沒有名稱权均,但它有參數(shù)列表、函數(shù)主...
    劉滌生閱讀 3,198評論 5 18
  • 注:之前關于Java8的認知一直停留在知道有哪些修改和新的API上,對Lambda的認識也是僅僅限于對匿名內(nèi)部類的...
    mualex閱讀 2,819評論 1 4
  • 準備3月21號出野外事件 1.確定課表 2.開好請假條 高階 干旱區(qū)地貌 spss 作業(yè):spss的作業(yè) ...
    愛學習的張小路閱讀 97評論 0 0