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