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