1. 程式人生 > >Java 8 ------------ Lambda 表示式

Java 8 ------------ Lambda 表示式

Lambda 表示式,也可稱為閉包,它是推動 Java 8 釋出的最重要新特性。

Lambda 允許把函式作為一個方法的引數(函式作為引數傳遞進方法中)。

使用Lambda 表示式可以使程式碼變的更加簡潔緊湊。 

1.語法

lambda 表示式的語法格式如下:

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

以下是lambda表示式的重要特徵:

·        可選型別宣告:不需要宣告引數型別,編譯器可以統一識別引數值。

·        可選的引數圓括號:一個引數無需定義圓括號,但多個引數需要定義圓括號。

·        可選的大括號:如果主體包含了一個語句,就不需要使用大括號。

·        可選的返回關鍵字:如果主體只有一個表示式返回值則編譯器會自動返回值,大括號需要指定明表示式返回了一個數值。

2. Lambda 表示式例項

public
class Java8Test { public static void main(String args[]) { Java8Test tester = new Java8Test(); // 型別宣告 MathOperation addition = (int a, int b) -> a + b; // 不用型別宣告 MathOperation subtraction = (a, b) -> a - b; // 大括號中的返回語句 MathOperation multiplication = (int
a, int b) -> { return a * b; }; // 沒有大括號及返回語句 MathOperation division = (int a, int b) -> a / b; System.out.println("10 + 5 = " + tester.operate(10, 5, addition)); System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + tester.operate(10, 5, division)); // 不用括號 GreetingService greetService1 = message -> System.out.println("Hello " + message); // 用括號 GreetingService greetService2 = (message) -> System.out.println("Hello " + message); greetService1.sayMessage("Runoob"); greetService2.sayMessage("Google"); } @FunctionalInterface interface MathOperation { int operation(int a, int b); } @FunctionalInterface interface GreetingService { void sayMessage(String message); } private int operate(int a, int b, MathOperation mathOperation) { return mathOperation.operation(a, b); } }

執行以上指令碼,輸出結果為:

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google

使用Lambda 表示式需要注意以下兩點:

·        Lambda 表示式主要用來定義行內執行的方法型別介面,例如,一個簡單方法介面。在上面例子中,我們使用各種型別的Lambda表示式來定義MathOperation介面的方法。然後我們定義了sayMessage的執行。

·        Lambda 表示式免去了使用匿名方法的麻煩,並且給予Java簡單但是強大的函式化的程式設計能力。

3 變數作用域

lambda 表示式只能引用標記了 final 的外層區域性變數,這就是說不能在lambda 內部修改定義在域外的區域性變數,否則會編譯錯誤。

在Java8Tester.java 檔案輸入以下程式碼:

public class Java8Tester {

    final static String salutation = "Hello! ";

    public static void main(String args[]) {
        GreetingService greetService1 = message -> System.out.println(salutation + message);
        greetService1.sayMessage("Runoob");
//====================相當於下面==============================
        GreetingService g = new GreetingService() {
            @Override
            public void sayMessage(String message) {
                System.out.println(salutation + message);
            }
        };
        g.sayMessage("jack");
//===========================================================
    }

    interface GreetingService {
        void sayMessage(String message);
    }
}

執行以上指令碼,輸出結果為:

Hello! Runoob
Hello! jack

我們也可以直接在lambda 表示式中訪問外層的區域性變數:

public class Java8Test1 {
    public static void main(String args[]) {
        final int num = 1;
        Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
        s.convert(2);  // 輸出結果為 3
    }

    public interface Converter<T1, T2> {
        void convert(int i);
    }
}

lambda 表示式的區域性變數可以不用宣告為 final,但是必須不可被後面的程式碼修改(即隱性的具有final 的語義)

public class Java8Test2 {
    public static void main(String args[]) {
        int num = 1;
        Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
        s.convert(2);
        num = 5;
    }

    public interface Converter<T1, T2> {
        void convert(int i);
    }
}
//報錯資訊:Local variable num defined in an enclosing scope must be final or effectively final

把num=5;註釋掉就不報錯了

在Lambda 表示式當中不允許宣告一個與區域性變數同名的引數或者區域性變數。
public class Java8Test2 {
    public static void main(String args[]) {
        String first = "";
        Comparator<String> comparator = (first, second) -> System.out.println(Integer.compare(first.length(), second.length()));  //編譯會出錯

        comparator.com("aaaaa", "bb");
    }

    public interface Comparator<T> {
        void com(String a, String b);
    }
}
報錯資訊:Variable 'first' is already defined in the scope
把String first = "";注掉就不報錯了。