讀書筆記–《寫給大忙人的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
這個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表達式中只能引用那些值不會改變的變量。