日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lambda 表达式详解~简化匿名内部类

發布時間:2024/7/23 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lambda 表达式详解~简化匿名内部类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本節將介紹如何使用Lambda表達式簡化匿名內部類的書寫,但Lambda表達式并不能取代所有的匿名內部類,只能用來取代函數接口(Functional Interface)的簡寫。先別在乎細節,看幾個例子再說。

例子1:無參函數的簡寫

如果需要新建一個線程,一種常見的寫法是這樣:

// JDK7 匿名內部類寫法 new Thread(new Runnable(){// 接口名@Overridepublic void run(){// 方法名System.out.println("Thread run()");} }).start();

上述代碼給Tread類傳遞了一個匿名的Runnable對象,重載Runnable接口的run()方法來實現相應邏輯。這是JDK7以及之前的常見寫法。匿名內部類省去了為類起名字的煩惱,但還是不夠簡化,在Java 8中可以簡化為如下形式:

// JDK8 Lambda表達式寫法 new Thread(() -> System.out.println("Thread run()")// 省略接口名和方法名 ).start();

上述代碼跟匿名內部類的作用是一樣的,但比匿名內部類更進一步。這里連接口名和函數名都一同省掉了,寫起來更加神清氣爽。如果函數體有多行,可以用大括號括起來,就像這樣

// JDK8 Lambda表達式代碼塊寫法 new Thread(() -> {System.out.print("Hello");System.out.println(" Hoolee");} ).start();

例子2:帶參函數的簡寫

如果要給一個字符串列表通過自定義比較器,按照字符串長度進行排序,Java 7的書寫形式如下:

// JDK7 匿名內部類寫法 List<String> list = Arrays.asList("I", "love", "you", "too"); Collections.sort(list, new Comparator<String>(){// 接口名@Overridepublic int compare(String s1, String s2){// 方法名if(s1 == null)return -1;if(s2 == null)return 1;return s1.length()-s2.length();} });

上述代碼通過內部類重載了Comparator接口的compare()方法,實現比較邏輯。采用Lambda表達式可簡寫如下:

// JDK8 Lambda表達式寫法 List<String> list = Arrays.asList("I", "love", "you", "too"); Collections.sort(list, (s1, s2) ->{// 省略參數表的類型if(s1 == null)return -1;if(s2 == null)return 1;return s1.length()-s2.length(); });

上述代碼跟匿名內部類的作用是一樣的。除了省略了接口名和方法名,代碼中把參數表的類型也省略了。這得益于javac的類型推斷機制,編譯器能夠根據上下文信息推斷出參數的類型,當然也有推斷失敗的時候,這時就需要手動指明參數類型了。注意,Java是強類型語言,每個變量和對象都必需有明確的類型。

簡寫的依據

也許你已經想到了,能夠使用Lambda的依據是必須有相應的函數接口(函數接口,是指內部只有一個抽象方法的接口)。這一點跟Java是強類型語言吻合,也就是說你并不能在代碼的任何地方任性的寫Lambda表達式。實際上Lambda的類型就是對應函數接口的類型。Lambda表達式另一個依據是類型推斷機制,在上下文信息足夠的情況下,編譯器可以推斷出參數表的類型,而不需要顯式指名。Lambda表達更多合法的書寫形式如下:

// Lambda表達式的書寫形式 Runnable run = () -> System.out.println("Hello World");// 1 ActionListener listener = event -> System.out.println("button clicked");// 2 Runnable multiLine = () -> {// 3 代碼塊System.out.print("Hello");System.out.println(" Hoolee"); }; BinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4 BinaryOperator<Long> addImplicit = (x, y) -> x + y;// 5 類型推斷

上述代碼中,1展示了無參函數的簡寫;2處展示了有參函數的簡寫,以及類型推斷機制;3是代碼塊的寫法;4和5再次展示了類型推斷機制。

自定義函數接口

自定義函數接口很容易,只需要編寫一個只有一個抽象方法的接口即可。

// 自定義函數接口 @FunctionalInterface public interface ConsumerInterface<T>{void accept(T t); }

上面代碼中的@FunctionalInterface是可選的,但加上該標注編譯器會幫你檢查接口是否符合函數接口規范。就像加入@Override標注會檢查是否重載了函數一樣。

有了上述接口定義,就可以寫出類似如下的代碼:

ConsumerInterface<String> consumer = str -> System.out.println(str);

進一步的,還可以這樣使用:

class MyStream<T>{private List<T> list;...public void myForEach(ConsumerInterface<T> consumer){// 1for(T t : list){consumer.accept(t);}} } MyStream<String> stream = new MyStream<String>(); stream.myForEach(str -> System.out.println(str));// 使用自定義函數接口書寫Lambda表達式

總結

以上是生活随笔為你收集整理的Lambda 表达式详解~简化匿名内部类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。