摘要:寫在前面最近在看實戰感覺這本書的排版紙質內容真的都超級棒個人覺得這本書還是很值得一讀本文簡單或詳細介紹一下的和表達式函數式接口是在才開始引入的首先看一下普通接口和函數式接口的區別普通接口指的是一些具有相同屬性和行為的類的抽象函數式接口也是同
What is Functional Interface?寫在前面: 最近在看<
>,感覺這本書的排版,紙質,內容真的都超級棒,個人覺得這本書還是很值得一讀.本文簡單或詳細介紹一下Java8的FunctionalInterface和Lambda表達式.
函數式接口(Functional Interface)是在Java8才開始引入的.首先看一下Java普通接口和函數式接口的區別:
Java普通接口: 指的是一些具有相同屬性和行為的類的抽象.
函數式接口: 也是同樣的理解方式,它是對一些相似的方法的抽象.
How can we say those methods are similar methods?1.如果定義的是一個泛型的函數式接口的話,比如:
@FunctionalInterface public interface MyFunction1{ R calculate(T t); }
那么所有只有一個參數并有返回值的函數都是MyFunction1的一個實例.也就是說這些方法都是相似的方法.
2.如果定義的是一個具體的函數式接口,比如:
@FunctionalInterface public interface MyFunction2 { void print(Integer i); }
那么所有參數是Integer類型的并且沒有返回值的函數都是MyFunction2的一個實例.也就是說這些方法都是相似的方法.
Java的接口可以當做函數的參數,那么函數式接口自然也可以,這就叫做行為參數化.
How to define and use a funtional interface?在Java8中已經定義了好多的函數式接口,比如:
java.lang.Runnable
java.util.Comparator
java.util.function.Predicate
java.util.function.Consumer
那么定義一個函數式接口,有哪些需要注意的地方呢?
1.添加@FunctionalInterface注解.
2.有且只有一個抽象方法.可以有多個default方法和static方法,但是這些方法都必須實現.
對于@FunctionalInterface注解,其實不加也可以,完全是可以通過編譯的,但前提是這個接口需要滿足上面的第二個注意點.
但又是為什么需要@FunctionalInterface?首先我們先看一個例子:
假設我們定義了一個函數式接口,但是忘記了添加了@FunctionInterface,同時這個函數式接口還沒被其他地方引用,如果這個時候我們又添加了一個抽象方法,是不會報錯的.因為這個接口有了多個抽象方法,所以這個接口就是一個普通的接口,而不是我們所期望的函數式接口.
這時候,如果添加了@FunctionalInterface注解的話,就會報錯,提示說這個接口具有多個抽象方法.實際上,個人理解@FunctionalInterface就是手動添加約束,說明這個接口就是函數式接口,只能有一個抽象方法.
接下來編寫并使用一個自定義函數式接口
// define a functional interface @FunctionalInterface public interface MyFunctionWhat is Lambda expression?{ R convert(T t); } // use a function interface public class Test { public static void main(String[] args) { MyFunction f = (Long l) -> String.valueOf(l); System.out.println(f.convert(10L)); // f: convert a Long to String MyFunction g = (String s) -> Long.parseLong(s); System.out.println(g.convert("10")); // g: convert a String to Long } }
咱們可以看一看<
可以把Lambda表達式理解為簡潔地表示可傳遞的匿名函數的一種方式: 它沒有名稱,但它有參數列表,函數主體,返回類型,可能還有一個可以拋出的異常列表.
匿名: 是因為它不像普通的方法有一個明確的名稱
函數: 是因為Lambda函數不像方法那樣屬于某個特定的類,但又和方法一樣,有參數列表,函數主體,返回值類型,還可能有可以拋出的異常列表
傳遞: Lambda表達式可以作為參數傳遞給方法或存儲在變量中
簡潔: 無須像匿名類那樣寫很多模板代碼
個人理解,Lambda表達式完全是服務于函數式接口的,就是為了在創建一個函數式接口實例時更加的直觀,簡潔.比如咱們要創建一個匿名類對象時,可以看一下普通接口和函數式接口的區別:
// a common interface public interface Common { void f(); void g(); } @FunctionalInterface public interface MyFunctionMethod Reference{ R convert(T); } public class Test { public static void main(String[] args){ // create a instance of common interface Common c = new Common() { @Override public void f() {} @Override public void g() {} }; // create a instance of functional interface MyFunction f = (Long l) -> String.valueOf(l); } }
說起方法引用之前,咱們先看一個例子
// 1 MyFunctionf = (Long l) -> String.valueOf(l); // 2: 通過Lambda的上下文推斷出l的數據類型 MyFunction f = l -> String.valueOf(l); // // 3 MyFunction f = String::valueOf;
第一種,第二種和第三種寫法的作用完全是一樣的,但顯然第三種的寫法更加簡潔.形如xxx::xxx這樣的表達式就是方法引用.方法引用可以被看做僅僅調用特定方法的Lambda的一種快捷寫法.
How many ways to replace lambda expression with method reference?總共有四種方法引用,下面咱們根據一個實例來說明并解釋這幾種方法引用.
// common class public class FunctionInstance { public Integer getLength(String str) { return Optional.ofNullable(str).orElse("").length(); // Optional也是Java8引入的 } } // test class public class MethodReference { public static void main(String[] args) { // 1.指向靜態方法的方法引用 //Functionf1 = s -> Integer.parseInt(s); Function f1 = Integer::parseInt; // 2.指向任意類型實例方法的方法引用,s為內部對象 //Predicate f2 = s -> s.isEmpty(); Predicate f2 = String::isEmpty; // 3.指向現有對象(外部對象)的實例方法的方法引用, instance為外部對象 //Function f3 = s -> instance.getLength(s); FunctionInstance instance = new FunctionInstance(); Function f3 = instance::getLength; // 4.構造函數引用 //Supplier f4 = () -> new MethodReference(); Supplier f4 = MethodReference::new; } }
2和3有人可能會混淆, 反正一開始看的時候我是沒區分出來.其實就看參數是為內部對象還是外部對象.內部對象就是用2,外部對象就是用3
內部對象: 指Lambda表達式中的對象,比如上面的s, 傳入的參數,屬于內部對象
外部對象: 指的是Lambda表達式外的對象,比如上面的instance
Summary函數式接口: 就是一個特殊的接口,只能有一個抽象方法.所以可以將函數式接口想象成是一個函數類型(比如Predicate,Consumer或自定義的函數式接口).
Lambda表達式: 則是簡化了匿名類對象的創建.正如我在上文所說的,Lambda表達式完全是服務于函數式接口的,正是因為了函數式接口的特殊性,所以才使用了Lambda表達式來創建一個函數類型實例,而不是像匿名類那樣寫一堆無用的模板代碼.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67966.html
摘要:函數式編程說前,先理解下什么是函數式編程,如果你是個純程序員,而且之前一直是沒有使用過,可能還沒有使用過這種編程方式。表達式可以表示閉包注意和數學傳統意義上的不同。意思就是說,只要是接口類型,我們都可以傳入表達式。在包下定義了各種函數接口 函數式編程 說lambdas前,先理解下什么是函數式編程,如果你是個純Java程序員,而且之前一直是沒有使用過Java8,可能還沒有使用過這種編程方...
摘要:由此可以看出,使用可以讓你的代碼在某些情況下達到何等的簡潔。如果沒有參數,那么前面的是必須存在的。我們知道中的,而其實就是一個只定義了一個抽象方法的。也就是說,可以訪問定義它的那個方法的局部變量。而在里面,還可以訪問所謂的局部變量。 上次在盆友圈發了一張照片 showImg(http://chriszou.com/images/lambda_example.png); 上面的兩段代碼是...
摘要:函數副作用會給程序設計帶來不必要的麻煩,引入潛在的,并降低程序的可讀性。所以只能采用這種曲線救國的方式。則是把這種曲線救國拿到了臺面上,并昭告天下,同時還對提供了一些語法支持。是自由變量,提供執行上下文,觸發閉包執行。 背景 自從2013年放棄了Java就再也沒有碰過。期間Java還發布了重大更新:引入lambda,但是那會兒我已經玩了一段時間Scala,對Java已經瞧不上眼。相比S...
摘要:在支持一類函數的語言中,表達式的類型將是函數。匿名函數的返回類型與該主體表達式一致如果表達式的主體包含一條以上語句,則表達式必須包含在花括號中形成代碼塊。注意,使用表達式的方法不止一種。 摘要:此篇文章主要介紹 Java8 Lambda 表達式產生的背景和用法,以及 Lambda 表達式與匿名類的不同等。本文系 OneAPM 工程師編譯整理。 Java 是一流的面向對象語言,除了部分簡...
閱讀 3490·2019-08-30 15:53
閱讀 3406·2019-08-29 16:54
閱讀 2190·2019-08-29 16:41
閱讀 2397·2019-08-23 16:10
閱讀 3377·2019-08-23 15:04
閱讀 1342·2019-08-23 13:58
閱讀 347·2019-08-23 11:40
閱讀 2452·2019-08-23 10:26