讀書筆記--《寫給大忙人的JavaSE 9 核心技術》—接口和lambda表達式

讀書筆記–《寫給大忙人的JavaSE 9 核心技術》—第3章

接口和lambda表達式

接口

它可以讓你在不提供實現的情況下,指定應該做什麼。(主要在設計階段用得到)

示例代碼

public interface Test1 {
    // 接口中的方法默認爲public
    public void saySomething(String something);
    // 在接口中可以定義靜態方法
    // 靜態方法只能由這個接口去調用,
    // 實現此接口的對象是不能調用的。
    static void sayMyName(){
        System.out.println("my name is Test1");
    }
    // 在接口中可以定義默認方法,實現此接口的類可以重新
    // 默認方法結束了這種經典模式——提供一個接口和實現該接口大多數或全部方法的伴隨類
    default void sayHello(){
        System.out.println("Hello");
    }
}

lambda

參考博文1

參考博文2

這個lambda 表達式 和 JavaScript裏面的箭頭函數很像

其核心是一種簡寫方式,可以取代大部分的匿名內部類,寫出更優雅的 Java 代碼。

 // 一行語句
 (String s1,String s2) -> s1.length() - s2.length()
 
 // 多行語句
  (String s1,String s2) ->{
      if(s1.length()>s2.length()){
          return "yes"
      }else{
          return "no"
      }
  }
  
 // 無參數
 () -> return "666"
 
 // 如果參數類型可以推導出來,則可以省略。
 // 示例見下方代碼

函數式接口

該接口只有一個抽象方法,該接口會被@FunctionalInterface這個註解所修飾

當你需要一個實現函數式接口的對象實例時,可以提供一個lambda表達式來創建。

import java.util.Arrays;
import java.util.Comparator;

public class Test3 {


    public int[] sort(int[] s) {
        //Arrays.sort(s);
        Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
        Comparator myComparator = new MyComparator();
        //自動裝包機制不能應用於數組。
        // 這裏 Comparator<Integer>,是Integer,而數組是int類型。這兩個不一樣!
        // 要把int改爲Integer
        // Arrays.sort(s ,myComparator); //會報錯!

        //Arrays.sort(a, myComparator);

        // lambda 表達式簡寫
        Arrays.sort(a, (n1, n2) -> {
                    if (n1 > n2) {
                        return -1;
                    } else {
                        return 1;
                    }
                }
        );
        for (int n : a) {
            System.out.println(n);
        }
        return s;
    }


    class MyComparator implements Comparator<Integer> {
        @Override
        //返回正數,零,負數各代表大於,等於,小於
        public int compare(Integer o1, Integer o2) {
            if (o1 > o2) {
                return -1;
            } else {
                return 1;
            }
        }


    }
}

作用域

lambda表達式的方法體與嵌套代碼有着相同的作用域。在lambda表達式中不允許聲明一個與局部變量同名的參數或者局部變量。

// 錯誤
int first = 0;
Comparator<Integer> comp = (first,second)->first > second

this指向問題

lambda表達式中this指向創建lambda表達式的外部類。

這裏的this指向App,而不是Runnable實例。 這一點和JavaScript中的箭頭函數很像,this指向調用此函數的對象。

class App() {
    public void doWork(){
        Runnable runnable = ()->{
            System.out.println(this.toString());
        }
    }
}

lambda一般情況下會被編譯成靜態匿名方法,引用的外部變量以參數的方式傳遞。

如果 lambda 裏使用了this 指標,則被編譯爲匿名內部方法,以讓 this 指針指向lambda 外部類。

閉包

閉包就是能夠讀取其他函數內部變量的函數。

這個概念在JavaScript中相當重要

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

在Java中有了lambda表達式,也有了閉包的概念,但是和JavaScript中的閉包有些不同。沒有JavaScript中的強大。

import java.util.function.Consumer;
public class Main {
    public static void main(String[] args) {

        int num = 10;

        Consumer<String> consumer = ele -> {
            System.out.println(num);
        };

        //num = num + 2;
        consumer.accept("hello");
    }
}

如果把註釋刪掉,則會報錯。因爲在lambda表達式中只能引用那些值不會改變的變量。

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