Java8---Lambda表達式

瞭解Lambda表達式之前,需要對匿名內部類與函數式接口瞭解。

一、函數式接口

1.有且只有一個抽象方法,但可以有多個非抽象方法。

2.可以隱式的轉換爲 Lambda 表達式。

3.可以在任意函數式接口上使用 @FunctionalInterface 註解,這樣做可以檢查它是否是一個函數式接口,同時javadoc也會包含一條聲明,聲明這個接口是一個函數式接口。

在 JDK1.8之前,java就包含了許多函數式接口,

java.lang.Runnable ,java.util.concurrent.Callable ,java.security.PrivilegedAction ,java.awt.event.ActionListener ,
java.io.FileFilter ,java.nio.file.PathMatcher ,java.lang.reflect.InvocationHandler ,java.beans.PropertyChangeListener ,
java.util.Comparator ,javax.swing.event.ChangeListener

java8 新增  java.util.function ,包下包含多個函數式接口,用來支持函數式編程。

/**
 * @author YoonaLt
 * 有參數,無返回值 的函數式接口
 */
@FunctionalInterface
public interface MyFunctionalInterface {

    /**
     * 函數式接口有且僅有一個抽象方法
     * 接口中,成員變量的默認修飾符爲 public static final,成員方法的默認修飾符爲 public abstract.
     *
     * @param s 參數
     */
    void onlyAbstractMethod(String s);

    /**
     * 可以含有多個其他非抽象方法
     * 這個方法是一個默認方法,使用默認方法的優勢是給接口添加新方法的同時不影響已有的實現.在工作中解                
     * 決接口的修改與現有的實現不兼容的問題是非常有效的.
     */
    default void otherFunction() {
        System.out.println("這是函數式接口的非抽象方法,可以有多個");
    }
}

 

二、Lambda表達式

Lambda 表達式,也可稱爲閉包,它是推動 Java 8 發佈的最重要新特性。Lambda 允許把 函數 作爲一個方法的 參數(函數作爲參數傳遞進方法中)。

使用Lam不打可以代替匿名內部類,匿名方法的使用,簡化代碼,減少類文件的生成。但是代碼可讀性不高,使用場景有限制。

Lambda表達式的寫法一般爲

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

其重要特性爲

  • 可選類型聲明:不需要聲明參數類型,編譯器可以統一識別參數值。
  • 可選的參數圓括號:一個參數無需定義圓括號,但多個參數需要定義圓括號。
  • 可選的大括號:如果主體只包含了一個語句,就不需要使用大括號。
  • 可選的返回關鍵字:如果主體只有一個表達式返回值則編譯器會自動返回值,大括號需要指定明表達式返回了一個數值。
//無參,使用空的 () 表示
() -> body

// 一個參數,參數可以用 () 包裹,也可以不用.當 body 主體只包含一個語句時,花括號可以省略不寫, param -> body;
(param) -> { body; } 或 param -> { body; } 

// 多個參數
(param1, param2...) -> { body }

參數 param param1 param2 的類型不需要指定(typeOne param1,typeTwo param2),編譯器可以從上下文推斷參數類型.

1.上面示例 有參數,無返回值 的函數式接口轉變爲 Lambda 表達式爲

MyFunctionalInterface myFunctionalInterface = (s) -> System.out.println(s); 
方法引用的方式
MyFunctionalInterface myFunctionalInterface = System.out::println;

myFunctionalInterface.onlyAbstractMethod("轉換爲Lambda表達式");

 

2.有參數,有返回值的函數式接口

/**
 * @author YoonaLt
 * 有參數,有返回值的函數式接口
 */
@FunctionalInterface
public interface MyTest<T, E> {
    E myMethod(T t);
}

轉變爲Lambda表達式爲

MyTest<String, Integer> myTest = (s) -> {return Integer.parseInt(s);};
方法引用的方式
MyTest<String, Integer> myTest = = Integer::parseInt;

myTest.myMethod("1");

 

3. Lambda 表達式比較典型的應用就是線程初始化

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("原方式創建一個線程");
            }
        }).start();

使用Lambda表達式後,就可以簡化爲

new Thread(() -> System.out.println("使用Lambda表達式")).start();

實際工作中並不推薦顯示的創建一個線程,強烈建議使用線程池的方式創建線程,這裏只是提供一個示例。

 

4.Lambda表達式也可在集合使用 forEach 方法時使用,比如下面這個示例

        List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6);
        List<Integer> result = new ArrayList<>();
        int min = 2;
        list.forEach(i -> {
            if (i > min) {
                result.add(i);
            }
        });
        result.forEach(System.out::println);

需要注意的是,Lambda表達式使用外部局部變量時,外部局部變量修飾符只能爲 final(如忽略不寫,編譯器會默認其爲 final 修飾),當你在 Lambda 表達式內部試圖修改外部局域變量時,會報錯

 

由於本人水平有限,難免有錯誤和疏漏,請不吝賜教.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章