Java 8特性探究(1):通往lambda之路
函式式介面
函式式介面(functional interface 也叫功能性介面,其實是同一個東西)。簡單來說,函式式介面是隻包含一個方法的介面。比如Java標準庫中的java.lang.Runnable和 java.util.Comparator都是典型的函式式介面。java 8提供 @FunctionalInterface作為註解,這個註解是非必須的,只要介面符合函式式介面的標準(即只包含一個方法的介面),虛擬機器會自動判斷, 但 最好在介面上使用註解@FunctionalInterface進行宣告,以免團隊的其他人員錯誤地往介面中新增新的方法。
Java中的lambda無法單獨出現,它需要一個函式式介面來盛放,lambda表示式方法體其實就是函式介面的實現,下面講到語法會講到
Lambda語法
包含三個部分
一個括號內用逗號分隔的形式引數,引數是函式式接口裡面方法的引數
一個箭頭符號:->
方法體,可以是表示式和程式碼塊,方法體函式式接口裡面方法的實現,如果是程式碼塊,則必須用{}來包裹起來,且需要一個return 返回值,但有個例外,若函式式接口裡面方法返回值是void,則無需{}
總體看起來像這樣
- (parameters) -> expression 或者 (parameters) -> { statements; }
看一個完整的例子,方便理解
- /**
- * 測試lambda表示式
- *
- * @author benhail
- */
- public class TestLambda {
- public static void runThreadUseLambda() {
- //Runnable是一個函式介面,只包含了有個無引數的,返回void的run方法;
- //所以lambda表示式左邊沒有引數,右邊也沒有return,只是單純的列印一句話
- new Thread(() ->System.out.println("lambda實現的執行緒")).start();
- }
- public static void runThreadUseInnerClass() {
- //這種方式就不多講了,以前舊版本比較常見的做法
- new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println("內部類實現的執行緒");
- }
- }).start();
- }
- public static void main(String[] args) {
- TestLambda.runThreadUseLambda();
- TestLambda.runThreadUseInnerClass();
- }
- }
可以看出,使用lambda表示式設計的程式碼會更加簡潔,而且還可讀。
方法引用
其實是lambda表示式的一個簡化寫法,所引用的方法其實是lambda表示式的方法體實現,語法也很簡單,左邊是容器(可以是類名,例項名),中間是"::",右邊是相應的方法名。如下所示:
- ObjectReference::methodName
一般方法的引用格式是
- 如果是靜態方法,則是ClassName::methodName。如 Object ::equals
- 如果是例項方法,則是Instance::methodName。如Object obj=new Object();obj::equals;
- 建構函式.則是ClassName::new
再來看一個完整的例子,方便理解
- import java.awt.FlowLayout;
- import java.awt.event.ActionEvent;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- /**
- *
- * @author benhail
- */
- public class TestMethodReference {
- public static void main(String[] args) {
- JFrame frame = new JFrame();
- frame.setLayout(new FlowLayout());
- frame.setVisible(true);
- JButton button1 = new JButton("點我!");
- JButton button2 = new JButton("也點我!");
- frame.getContentPane().add(button1);
- frame.getContentPane().add(button2);
- //這裡addActionListener方法的引數是ActionListener,是一個函式式介面
- //使用lambda表示式方式
- button1.addActionListener(e -> { System.out.println("這裡是Lambda實現方式"); });
- //使用方法引用方式
- button2.addActionListener(TestMethodReference::doSomething);
- }
- /**
- * 這裡是函式式介面ActionListener的實現方法
- * @param e
- */
- public static void doSomething(ActionEvent e) {
- System.out.println("這裡是方法引用實現方式");
- }
- }
可以看出,doSomething方法就是lambda表示式的實現,這樣的好處就是,如果你覺得lambda的方法體會很長,影響程式碼可讀性,方法引用就是個解決辦法