Java8 lambda表達式
lambda表達式初識
lambda表達式的重要用法就是簡化某些匿名類的寫法,實際上lambda不僅僅是匿名內部類的語法糖,JVM內部也是通過invokedynamic指令來實現lambda表達式的。
也正是因爲如此匿名類在編譯以後會創建一個新的匿名內部類出來,而由於Lambda是調用JVMinvokedynamic指令實現的,所以並不會產生新類。
其實lambda表達式描述了一個代碼塊(匿名方法);可以將其作爲參數傳遞給構造方法或者普通方法以便後續執行,如下:
()->System.out.println("冢狐")
- 其中()爲lambda表達的參數列表(可以有也可以沒有)
- ->標識這段代碼爲lambda表達式,後面就是要執行的代碼。
其中lambda最常見的用途就是新建線程,有時候爲了省事會用下面的方法創建並啓動一個線程
public static void main(String[] args) {
new Thread(() -> System.out.println("冢狐")).start();
}
Lambda語法
lambda標準的語法如下:
(parameter-list)->{express-or-statements}
-
其中()中的parameter-list是以逗號分隔的參數,在其中可以指定參數類型,也可以不執行(編譯器會根據上下文進行推斷)
-
->作爲lambda的標識符,主要作用就是告訴這是一個lambda表達式
-
{}中爲lambda的主體,主要通過其中的代碼進行要做的事情
-
爲變量賦值
Runnable r = (){System.out.print("冢狐")};
-
作爲return的結果:
static FileFilter getFilter(String ex){ return (pathname)->pathname.toString().endWith(ex); }
-
作爲數組元素:
final PathMatcher matchers[] = { (path) -> path.toString().endsWith("zhong"), (path) -> path.toString().endsWith("hu") };
-
作爲普通方法或者構造方法的參數
new Thread(() -> System.out.println("冢狐")).start();
-
使用Lambda表達式的要求
能夠使用lambda的依據就是必須有相應的函數接口。
函數接口是指內部只有一個抽象方法的接口,這一點和java是強類型語言吻合,即不能在代碼的任何地方使用lambda表達式。
lambda的類型就是對於函數接口的類型。
自定義函數接口
自定義函數接口還是比較容易的,只需要編寫一個只有一個抽象方法的接口即可
// 自定義函數接口
public static void main(String[] args) {
ConsumerInterFace<String> consumer = str-> System.out.println(str);
consumer.accept("自定義函數接口");
}
@FunctionalInterface
public interface ConsumerInterFace<T>{
void accept(T t);
}
java內置四大核心函數式接口
函數式接口 | 參數列表 | 返回類型 | 用途 |
---|---|---|---|
Consumer<T>消費型接口 | T | void | 對類型爲T的對象應用操作,包含方法void accept(T t); |
Supplier<T>供給型接口 | 無 | T | 返回類型爲T的對象,包含方法T get(); |
Function<T,R>函數型接口 | T | R | 對類型爲T的對象應用操作,並返回結果類型爲R的對象,包含方法R apple(T t); |
Predicate<T>斷定型接口 | T | boolean | 確定類型爲T的對象是否滿足某約束,並返回boolean值,包含方法boolean test(T t); |
Lambda和this關鍵字
由於lambda表達式並不會引入新的作用域,即lambda表達式的主體內使用的this關鍵字和其所在的類實例相同。
示例:
public class Player {
public static void main(String[] args) {
new Player().work();
}
public void work() {
System.out.printf("this = %s%n", this);
Runnable r = new Runnable() {
@Override
public void run() {
System.out.printf("this = %s%n", this);
}
};
new Thread(r).start();
new Thread(() -> System.out.printf("this = %s%n", this)).start();
}
}
work()中的代碼可以分爲三個部分:
- 單獨的this關鍵字
- 這裏的this爲main()方法中通過new關鍵字創建的Player對象
- 匿名內部類中的this關鍵字
- 這裏的this爲work()方法中通過new關鍵字創建的Runnable對象
- Lambda表達式中的this關鍵字
- 這個和第一個單獨的this是一個
輸出結果:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Nuq1rUxN-1592796226199)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200622101950.png)]