成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java8: Functional Interface and Lambda Expression

sunnyxd / 1977人閱讀

摘要:寫在前面最近在看實(shí)戰(zhàn)感覺這本書的排版紙質(zhì)內(nèi)容真的都超級(jí)棒個(gè)人覺得這本書還是很值得一讀本文簡單或詳細(xì)介紹一下的和表達(dá)式函數(shù)式接口是在才開始引入的首先看一下普通接口和函數(shù)式接口的區(qū)別普通接口指的是一些具有相同屬性和行為的類的抽象函數(shù)式接口也是同

寫在前面: 最近在看<>,感覺這本書的排版,紙質(zhì),內(nèi)容真的都超級(jí)棒,個(gè)人覺得這本書還是很值得一讀.本文簡單或詳細(xì)介紹一下Java8的FunctionalInterface和Lambda表達(dá)式.

What is Functional Interface?

函數(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 MyFunction {
    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
    }
}
What is Lambda expression?

咱們可以看一看<>這本書中的定義:

可以把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 MyFunction {
    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);
    }
}
Method Reference

說起方法引用之前,咱們先看一個(gè)例子

    // 1
    MyFunction f = (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)方法的方法引用
        //Function f1 = 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

相關(guān)文章

  • Java8 lambda支持

    摘要:函數(shù)式編程說前,先理解下什么是函數(shù)式編程,如果你是個(gè)純程序員,而且之前一直是沒有使用過,可能還沒有使用過這種編程方式。表達(dá)式可以表示閉包注意和數(shù)學(xué)傳統(tǒng)意義上的不同。意思就是說,只要是接口類型,我們都可以傳入表達(dá)式。在包下定義了各種函數(shù)接口 函數(shù)式編程 說lambdas前,先理解下什么是函數(shù)式編程,如果你是個(gè)純Java程序員,而且之前一直是沒有使用過Java8,可能還沒有使用過這種編程方...

    Betta 評(píng)論0 收藏0
  • Java 8的Lambda及其在Android 開發(fā)中的應(yīng)用

    摘要:由此可以看出,使用可以讓你的代碼在某些情況下達(dá)到何等的簡潔。如果沒有參數(shù),那么前面的是必須存在的。我們知道中的,而其實(shí)就是一個(gè)只定義了一個(gè)抽象方法的。也就是說,可以訪問定義它的那個(gè)方法的局部變量。而在里面,還可以訪問所謂的局部變量。 上次在盆友圈發(fā)了一張照片 showImg(http://chriszou.com/images/lambda_example.png); 上面的兩段代碼是...

    liuhh 評(píng)論0 收藏0
  • Introducing FP in Java8

    摘要:函數(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...

    Prasanta 評(píng)論0 收藏0
  • 深入淺出 Java 8 Lambda 表達(dá)式

    摘要:在支持一類函數(shù)的語言中,表達(dá)式的類型將是函數(shù)。匿名函數(shù)的返回類型與該主體表達(dá)式一致如果表達(dá)式的主體包含一條以上語句,則表達(dá)式必須包含在花括號(hào)中形成代碼塊。注意,使用表達(dá)式的方法不止一種。 摘要:此篇文章主要介紹 Java8 Lambda 表達(dá)式產(chǎn)生的背景和用法,以及 Lambda 表達(dá)式與匿名類的不同等。本文系 OneAPM 工程師編譯整理。 Java 是一流的面向?qū)ο笳Z言,除了部分簡...

    wdzgege 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

sunnyxd

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<