1. 程式人生 > >Java 8特性探究(1):通往lambda之路

Java 8特性探究(1):通往lambda之路

函式式介面

函式式介面(functional interface 也叫功能性介面,其實是同一個東西)。簡單來說,函式式介面是隻包含一個方法的介面。比如Java標準庫中的java.lang.Runnable和 java.util.Comparator都是典型的函式式介面。java 8提供 @FunctionalInterface作為註解,這個註解是非必須的,只要介面符合函式式介面的標準(即只包含一個方法的介面),虛擬機器會自動判斷, 但 最好在介面上使用註解@FunctionalInterface進行宣告,以免團隊的其他人員錯誤地往介面中新增新的方法。

Java中的lambda無法單獨出現,它需要一個函式式介面來盛放,lambda表示式方法體其實就是函式介面的實現,下面講到語法會講到

Lambda語法

包含三個部分

一個括號內用逗號分隔的形式引數,引數是函式式接口裡面方法的引數

一個箭頭符號:->

方法體,可以是表示式和程式碼塊,方法體函式式接口裡面方法的實現,如果是程式碼塊,則必須用{}來包裹起來,且需要一個return 返回值,但有個例外,若函式式接口裡面方法返回值是void,則無需{}

總體看起來像這樣


 
  1. (parameters) -> expression 或者 (parameters) -> { statements; } 

看一個完整的例子,方便理解


 
  1. /** 
  2.  * 測試lambda表示式 
  3.  * 
  4.  * @author benhail 
  5.  */ 
  6. public class TestLambda { 
  7.  
  8.     public static void runThreadUseLambda() { 
  9.         //Runnable是一個函式介面,只包含了有個無引數的,返回void的run方法;
     
  10.         //所以lambda表示式左邊沒有引數,右邊也沒有return,只是單純的列印一句話 
  11.         new Thread(() ->System.out.println("lambda實現的執行緒")).start();  
  12.     } 
  13.  
  14.     public static void runThreadUseInnerClass() { 
  15.         //這種方式就不多講了,以前舊版本比較常見的做法 
  16.         new Thread(new Runnable() { 
  17.             @Override 
  18.             public void run() { 
  19.                 System.out.println("內部類實現的執行緒"); 
  20.             } 
  21.         }).start(); 
  22.     } 
  23.  
  24.     public static void main(String[] args) { 
  25.         TestLambda.runThreadUseLambda(); 
  26.         TestLambda.runThreadUseInnerClass(); 
  27.     } 

可以看出,使用lambda表示式設計的程式碼會更加簡潔,而且還可讀。

方法引用

其實是lambda表示式的一個簡化寫法,所引用的方法其實是lambda表示式的方法體實現,語法也很簡單,左邊是容器(可以是類名,例項名),中間是"::",右邊是相應的方法名。如下所示:


 
  1. ObjectReference::methodName 

一般方法的引用格式是

  1. 如果是靜態方法,則是ClassName::methodName。如 Object ::equals
  2. 如果是例項方法,則是Instance::methodName。如Object obj=new Object();obj::equals;
  3. 建構函式.則是ClassName::new

再來看一個完整的例子,方便理解


 
  1. import java.awt.FlowLayout; 
  2. import java.awt.event.ActionEvent; 
  3. import javax.swing.JButton; 
  4. import javax.swing.JFrame; 
  5.  
  6. /** 
  7.  * 
  8.  * @author benhail 
  9.  */ 
  10. public class TestMethodReference { 
  11.  
  12.     public static void main(String[] args) { 
  13.  
  14.         JFrame frame = new JFrame(); 
  15.         frame.setLayout(new FlowLayout()); 
  16.         frame.setVisible(true); 
  17.          
  18.         JButton button1 = new JButton("點我!"); 
  19.         JButton button2 = new JButton("也點我!"); 
  20.          
  21.         frame.getContentPane().add(button1); 
  22.         frame.getContentPane().add(button2); 
  23.         //這裡addActionListener方法的引數是ActionListener,是一個函式式介面 
  24.         //使用lambda表示式方式 
  25.         button1.addActionListener(e -> { System.out.println("這裡是Lambda實現方式"); }); 
  26.         //使用方法引用方式 
  27.         button2.addActionListener(TestMethodReference::doSomething); 
  28.          
  29.     } 
  30.     /** 
  31.      * 這裡是函式式介面ActionListener的實現方法 
  32.      * @param e  
  33.      */ 
  34.     public static void doSomething(ActionEvent e) { 
  35.          
  36.         System.out.println("這裡是方法引用實現方式"); 
  37.          
  38.     } 

可以看出,doSomething方法就是lambda表示式的實現,這樣的好處就是,如果你覺得lambda的方法體會很長,影響程式碼可讀性,方法引用就是個解決辦法