摘要:表達式會復制一份自由變量的值,對象的話就是復制一個引用,因此表達式離開了原作用域也能正常使用自由變量。不過表達式對自由變量是有要求的,自由變量必須是不可變的,原因是并發(fā)執(zhí)行時不安全。
序
Java 8新增的lambda表達式毫無疑問是令人非常激動的,從此我們可以非常簡潔的定義和使用代碼塊而不是用繁瑣的匿名內部類來實現。而接口是lambda表達式的基礎,要理解lambda表達式就要先理解接口的概念。
接口在Java中接口是對類行為的抽象。似乎繼承也能做到這件事,它們的區(qū)別在于Java中類只能有一個父類,而接口是可以實現多個的。所以接口更傾向于類的一部分抽象,也就是行為的抽象,而不是類本身的抽象。
語法要定義一個接口很簡單,使用關鍵字interface后面再跟上接口名稱就可以了。類可以用implements關鍵字來實現接口。
public interface A { void test(); }
接口不允許有實例域,但可以有常量
接口中的域都會自動聲明為public static final
接口中的方法都會自動聲明為public
接口中可以聲明抽象方法,Java 8以后還可以聲明靜態(tài)方法和默認方法
// Java 8版本 public interface A { //常量 String AUTHOR = "Yuicon"; //抽象方法 void test(); //默認方法 default void testDefault(){} //靜態(tài)方法 static void testStatic(){} }默認方法的沖突
如果一個類實現的接口中有簽名相同的默認方法,那么就會有沖突的問題。在Java中解決這個問題有一些明確的規(guī)則:
在超類中已有同簽名的方法,就會忽略接口中的默認方法,也就是超類優(yōu)先
接口中默認方法和另一個默認方法或者抽象方法沖突的,必須要覆蓋這個方法
lambda表達式lambda表達式是一個可傳遞的代碼塊,可以在以后執(zhí)行一次或多次。之所以會有這么一個特性,是因為原先在Java中傳遞一個代碼塊是非常繁瑣的一件事情,必須要構建一個對象。比如常用的Runnable接口:
Runnable runnable = new Runnable() { @Override public void run() { System.out.println("我好麻煩"); } };
lambda版本就非常簡潔:
Runnable runnable = () -> System.out.println("我很簡潔");
是的,lambda版本只要一行就完成了任務。
語法在我看來lambda表達式是一種語法糖,它提供了一種簡潔、易懂的方式來實現只有一個抽象方法的接口。關鍵詞是只有一個抽象方法的接口,比如這樣一個接口:
@FunctionalInterface public interface A { void test(); } A a = () -> System.out.println("test"); a.test();
其中@FunctionalInterface注解是用來標記接口為函數式接口,去掉也不會影響功能,添加了這個注解后編譯器會檢查接口內是否只有一個抽象方法。
lambda表達式主要有以下要素:
參數
箭頭 ->
方法體
自由變量
參數lambda表達式的參數和普通方法的參數并無太大區(qū)別,主要的區(qū)別點有:
如果參數的類型可以被編譯器推導出來,那么可以省略參數類型
如果參數的類型可以被編譯器推導出來,而且只有一個參數,那么就可以省略括號
Consumer方法體consumer = s -> System.out.println(s);
lambda表達式的方法體內只有一條語句的時候,可以不加大括號且無需指定返回值,編譯器會自動推導。方法體內有多條語句的時候就需要加大括號并手動指定返回值,不過lambda表達式是沒有自己的作用域的,這點需要注意。
Supplier自由變量supplier = () -> { String s = "test"; return s; };
自由變量是指非參數而且不在方法體內定義的變量,我們來看一個例子:
public static void main(String[] args) { String test = "test"; A a = () -> System.out.println(test); a.test(); }
例子中的變量test就是一個自由變量,代碼塊a引用了外部方法的變量,這就是一個閉包了。lambda表達式會復制一份自由變量的值,對象的話就是復制一個引用,因此lambda表達式離開了原作用域也能正常使用自由變量。不過lambda表達式對自由變量是有要求的,自由變量必須是不可變的,原因是并發(fā)執(zhí)行時不安全。以下代碼是錯誤的:
for (int i = 0; i < 9; i++) { // error A a = () -> System.out.println(i); }方法引用
方法引用是語法糖的語法糖,顧名思義方法引用是引用已有方法的一個特性。它的形式如下:
@FunctionalInterface public interface A { void test(String s); } A a = System.out::println; a.test("test");
之所以說方法引用是語法糖的語法糖是因為A a = System.out::println;完全等價于A a = s -> System.out.println(s);,方法引用有5種情況:
object::instanceMethod
this::instanceMethod
super::instanceMethod // 超類方法
Class::staticMethod
Class::instanceMethod
前4種情況和lambda表達式是完全等價的,第5種情況比較特殊,第一個參數會成為方法的目標。比如String::compareToIgnoreCase等同于 (x, y)-> x.compareToIgnoreCase(y)。
構造器引用構造器引用是引用對象的構造器,用的是特殊的方法名new,使用形式為Object::new,使用方法和方法引用差不多。
常用函數式接口JDK已經提供了常用的函數式接口基本上是不需要自己寫函數式接口的。
后記一周一篇是不可能一周一篇的,人懶起來就和咸魚一樣根本不會動彈。還好人是會變通的,上周少了這周補上不就行了!Java被人詬病繁瑣不是一天兩天了,在各種新生編程語言的追趕下Java也要加快自己的演進了,更改發(fā)布周期就是一個很好的信號。
參考資料:
《Java核心技術 卷1》
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76841.html
摘要:即接口是用來描述對象具有的某種功能,而不關心具體實現。或者說,接口好比服務商指定的標準,由代加工工廠遵守來生產。內部類允許在類中定義其它類,這種定義在類中的類叫做嵌套類。局部類是聲明,匿名類是表達式。匿名類當需要聲明字段或其它方法時。 接口 在繼承那篇博文里,我們已經簡單了解了 Java 接口的概念。即:接口是用來描述對象具有的某種「功能」,而不關心具體實現。或者說,接口好比服務商指定...
摘要:新特性總覽標簽本文主要介紹的新特性,包括表達式方法引用流默認方法組合式異步編程新的時間,等等各個方面。還有對應的和類型的函數連接字符串廣義的歸約匯總起始值,映射方法,二元結合二元結合。使用并行流時要注意避免共享可變狀態(tài)。 Java8新特性總覽 標簽: java [TOC] 本文主要介紹 Java 8 的新特性,包括 Lambda 表達式、方法引用、流(Stream API)、默認方...
摘要:在支持一類函數的語言中,表達式的類型將是函數。匿名函數的返回類型與該主體表達式一致如果表達式的主體包含一條以上語句,則表達式必須包含在花括號中形成代碼塊。注意,使用表達式的方法不止一種。 摘要:此篇文章主要介紹 Java8 Lambda 表達式產生的背景和用法,以及 Lambda 表達式與匿名類的不同等。本文系 OneAPM 工程師編譯整理。 Java 是一流的面向對象語言,除了部分簡...
摘要:概述簡介是一個匿名函數,我們可以把表達式理解為是一段可以傳遞的代碼將代碼像數據一樣進行傳遞。作為一種更緊湊的代碼風格,使的語言表達能力得到了提升。任何滿足單一抽象方法法則的接口,都會被自動視為函數接口。 1. 概述 1.1 簡介 Lambda 是一個匿名函數,我們可以把 Lambda 表達式理解為是一段可以傳遞的代碼(將代碼像數據一樣進行傳遞)。可以寫出更簡潔、更靈活的代碼。作為一種更...
摘要:編程語言將函數作為一等公民,函數可以被作為參數或者返回值傳遞,因為它被視為對象。是表示已注釋接口是函數接口的注釋。如果一個函數有一個或多個參數并且有返回值呢為了解決這個問題,提供了一系列通用函數接口,在包里。 【編者按】雖然 Java 深得大量開發(fā)者喜愛,但是對比其他現代編程語言,其語法確實略顯冗長。但是通過 Java8,直接利用 lambda 表達式就能編寫出既可讀又簡潔的代碼。作者...
閱讀 712·2021-11-22 13:52
閱讀 1518·2021-09-27 13:36
閱讀 2818·2021-09-24 09:47
閱讀 2172·2021-09-22 15:48
閱讀 3600·2021-09-22 15:39
閱讀 1463·2019-08-30 12:43
閱讀 2918·2019-08-29 18:39
閱讀 3181·2019-08-29 12:51