Java JDK1.8新特性__Java

來源:互聯網
上載者:User

一、lambda含義

    lambda表示數學符號“λ”,電腦領域中λ代表“λ演算”,表達了電腦中最基本的概念:“調用”和“置換”。在很多動態語言和C#中都有相應的lambda文法,這類文法都為了簡化代碼,提高運行效率。


二、lambda 項目的背景,參考這裡。

    無論是物件導向語言還是函數式語言,基本數值都可以被動態封裝入程式動作:物件導向語言通過“方法”,函數式語言通過“函數。

    介於“方法”和“函數”的定義有很多種,補充下IBM知識庫的解釋:

在物件導向語言中,方法不是一階值(First-class value),在函數式語言中,函數是一階值。在函數式語言中,函數可以作為另一個函數的傳回值或參數,還可以作為一個變數的值,函數可以嵌套定義,而在物件導向語言中的的“方法”做不到這點。

    Java可以說是物件導向語言的代表,如果要調用其方法,需要先建立對象。不過Java對象都是“重量級”的,執行個體化具體的類的對象,需要經過定義和申明兩個階段。比如定義方法,並給內部欄位賦初始值。但是一個對象只包含一個方法的情況很多,比如實現API中的“回調介面”功能的類,在swing中有介面:


Java代碼   <span><span><span style="">public interface ActionListener {        void actionPerformed(ActionEvent e);   }</span></span></span>  


   現有的實現方式大多是:


Java代碼   <span><span><span style="">button.addActionListener(new ActionListener() {      public void actionPerformed(ActionEvent e) {        ui.dazzle(e.getModifiers());     }   });</span></span></span>  


    很多現有的類庫都基於這種設計實現,所以對於代碼被明確定義運行在單獨線程的API來說,匿名內部類尤為重要。這些匿名內部類只存在於建立它的線程中。但是在並行計算領域,CPU的製造商著力發展多核技術來提升CPU的功能,這麼做幾乎無法依靠多核的優勢來提升其效能。



    鑒於回呼函數和其他功能式文法的關係越來越密切,所以必須建立儘可能的輕量級的資料模型(從編碼角度而言,效能方面下文再說)。對於這點來說匿名內部類的缺點如下:

1. 文法相對複雜。

2. 在調用內部類的上下文中,指引和this的指代容易混淆。

3. 類載入和執行個體建立文法不可避免。

4. 不能引用外部的非final對象。

5. 不能抽象化控制流程程



    針對這些問題,lambda項目致力於

1. 消除問題1和問題2,通過引入更簡單的運算式和局部變數的定義規則。

2. 迴避問題3,定義更靈活更友善的文法。這裡只是迴避,類載入和執行個體化本身不可避免。下文會解釋。

3. 改善問題4,允許使用者使用最終有效局部變數。


    不過lambda項目目前並不能解決所有關於內部類的問題。問題4和問題5沒有完全解決,這計劃在將類版本中繼續改善。對於效能方面,原文也沒有提,不過後面有些補充。



三、lambda用法

    通過上文可以瞭解到,lambda文法是針對“回調介面”和“匿名內部類”作出的改進,所以lambda的文法目前僅對於部分介面,這些介面的特點是只含一個抽象方法,在lambda項目中,早期稱為SAM類型(SAM = single abstract method 即單一抽象方法)。在最新的文檔中(即這個版本),它們有了新名字,叫函數介面(functional interface),比如:
1 java.lang.Runnable 2 java.util.concurrent.Callable 3 java.security.PrivilegedAction 4 java.util.Comparator 5 java.io.FileFilter 6 java.nio.file.PathMatcher 7 java.lang.reflect.InvocationHandler 8 java.beans.PropertyChangeListener 9 java.awt.event.ActionListener 10 javax.swing.event.ChangeListener
lambda的文法包括三部分 1、參數列表 2、箭頭符號"->" 3、代碼塊。



    其中代碼塊很像一個方法體,return語句將控制權交還給匿名方法(anonymous method,即lambda運算式)的調用者;break和continue不能出現在函數體的頂部,不過可以出現在內部的迴圈裡;如果代碼塊得出最終結果,那麼每一個控制路徑(control path) 必須都有返回或拋出異常。

如果代碼塊只有簡單一行,可以省略return關鍵字和“{}”符號(以下所寫的例子都是基於JDK 1.8 lambda預覽版),比如:



Java代碼   <span><span><span style="">public class LambdaTest {           public static void main(String... args) {           //這裡有{}和return 以及 ;           Runnable r = () -> { System.out.println("hello world"); };                      //這裡不需要{}和return           java.util.Comparator<String> c = (String s1, String s2) -> s2.length()-s1.length();                   r.run();           System.out.println(c.compare("s1", "12323"));       }   }</span></span></span>  



輸出為:

hello world

3



除了這些現有介面,我們還可以自訂函數介面:


Java代碼   <span><span><span style="">public class LambdaTest {       interface lambdaInterface {           public void me(String str);       }          public static void main(String... args) {           lambdaInterface li = (String s)->{System.out.println(s);};           li.me("hello world!");       }   }</span></span></span>  

 輸出為:


hello world!


    新的lambda方法從文法上的確是簡化了很多。和lambda第一次發布的文法相比也優雅很多。



四、lambda代碼塊的位元組碼


看完了文法的確很簡單,那麼lambda是怎麼實現的,就得從位元組碼考察了。這裡和匿名內部類做個對比,編譯如下代碼:


Java代碼   <span><span><span style="">public class LambdaTest 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.