第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

函數(shù)式接口概述

在 Java 里面,所有的方法參數(shù)都是有固定類型的,比如將數(shù)字 9 作為參數(shù)傳遞給一個(gè)方法,它的類型是 int;字符串 “9” 作為參數(shù)傳遞給方法,它的類型是 String。那么 Lambda 表達(dá)式的類型由是什么呢?通過(guò)本節(jié)我們學(xué)習(xí)什么是函數(shù)式接口,它與 Lambda 表達(dá)式的關(guān)系。

1. 什么是函數(shù)式接口

函數(shù)式接口(Functional Interface)就是一個(gè)有且僅有一個(gè)抽象方法,但是可以有多個(gè)非抽象方法的接口,它可以被隱式轉(zhuǎn)換為 Lambda 表達(dá)式。

Tips: 換句話說(shuō)函數(shù)式接口就是 Lambda 表達(dá)式的類型。

在函數(shù)式接口中,單一方法的命名并不重要,只要方法簽名和 Lambda 表達(dá)式的類型匹配即可。

Tips: 通常我們會(huì)為接口中的參數(shù)其一個(gè)有意義的名字來(lái)增加代易讀性,便于理解參數(shù)的用途。

函數(shù)式接口有下面幾個(gè)特點(diǎn):

  1. 接口有且僅有一個(gè)抽象方法;
  2. 允許定義靜態(tài)方法;
  3. 允許定義默認(rèn)方法;
  4. 允許 java.lang.Object 中的 public 方法;
  5. 推薦使用 @FunctionInterface 注解(如果一個(gè)接口符合函數(shù)式接口的定義,加不加該注解都沒(méi)有影響,但加上該注解可以更好地讓編譯器進(jìn)行檢查)。

我們來(lái)看函數(shù)式接口的例子:

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
@FunctionalInterface
interface TestFunctionalInterface
{
    //抽象方法
    public void doTest();
    //java.lang.Object中的public方法
    public boolean equals(Object obj);
    public String toString();
    //默認(rèn)方法
    public default void doDefaultMethod(){System.out.println("call dodefaultMethod");}
    //靜態(tài)方法
    public static void doStaticMethod(){System.out.println("call doStaticMethod");}


    public static void main(String...s){
        //實(shí)現(xiàn)抽象方法
        TestFunctionalInterface test = ()->{
            System.out.println("call doTest");
        };
        //調(diào)用抽象方法
        test.doTest();
        //調(diào)用默認(rèn)方法
        test.doDefaultMethod();
        //調(diào)用靜態(tài)方法
        TestFunctionalInterface.doStaticMethod();
        //調(diào)用toString方法
        System.out.println(test.toString());
    }
}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

我們將得到如下結(jié)果:

call doTest
call dodefaultMethod
call doStaticMethod
com.github.x19990416.item.TestFunctionalInterface$$Lambda$1/0x00000008011e0840@63961c42

我們通過(guò) toString 方法可以發(fā)現(xiàn),test 對(duì)象被便已成為 TestFunctionalInterface 的一個(gè) Lambda 表達(dá)式。

2. @FunctionalInterface

接下來(lái)我們?cè)賮?lái)看下 @FunctionalInterface注解的作用:

首先我們定義一個(gè)接口 TestFunctionalInterface,包含兩個(gè)方法 doTest1doTest2

interfact TestFunctionalInterface{
    //一個(gè)抽象方法
    public void doTest1();
    //另一個(gè)抽象方法
    public void doTest2();
}

此時(shí)對(duì)于編譯期而言我們的代碼是沒(méi)有任何問(wèn)題的,它會(huì)認(rèn)為這就是一個(gè)普通的接口。當(dāng)我們使用 @FunctionalInterface 后:

//這是一個(gè)錯(cuò)誤的例子?。。?!
@FunctionalInterface
interfact TestFunctionalInterface{
    //一個(gè)抽象方法
    public void doTest1();
    //另一個(gè)抽象方法
    public void doTest2();
}

此時(shí),會(huì)告訴編譯器這是一個(gè)函數(shù)式接口,但由于接口中有兩個(gè)抽象方法,不符合函數(shù)式接口的定義,此時(shí)編譯器會(huì)報(bào)錯(cuò):

Multiple non-overriding abstract methods found in interface

3. 常用的函數(shù)式接口

JDK 8 之后新增了一個(gè)函數(shù)接口包 java.util.function 這里面包含了我們常用的一些函數(shù)接口:

接口 參數(shù) 返回類型 說(shuō)明
Predicate T boolean 接受一個(gè)輸入?yún)?shù) T,返回一個(gè)布爾值結(jié)果
Supplier None T 無(wú)參數(shù),返回一個(gè)結(jié)果,結(jié)果類型為 T
Consumer T void 代表了接受一個(gè)輸入?yún)?shù) T 并且無(wú)返回的操作
Function<T,R> T R 接受一個(gè)輸入?yún)?shù) T,返回一個(gè)結(jié)果 R
UnaryOperator T T 接受一個(gè)參數(shù)為類型 T,返回值類型也為 T
BinaryOperator (T,T) T 代表了一個(gè)作用于于兩個(gè)同類型操作符的操作,并且返回了操作符同類型的結(jié)果

3.1 Predicate

條件判斷并返回一個(gè)Boolean值,包含一個(gè)抽象方法 (test) 和常見的三種邏輯關(guān)系 與 (and) 、或 (or) 、非 (negate) 的默認(rèn)方法。

Predicate 接口通過(guò)不同的邏輯組合能夠滿足我們常用的邏輯判斷的使用場(chǎng)景。

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
import java.util.function.Predicate;

public class DemoPredicate {
    public static void main(String[] args) {
        //條件判斷
        doTest(s -> s.length() > 5);
        //邏輯非
        doNegate(s -> s.length() > 5);
        //邏輯與
        boolean isValid = doAnd(s -> s.contains("H"),s-> s.contains("w"));
        System.out.println("邏輯與的結(jié)果:"+isValid);
        //邏輯或
        isValid = doOr(s -> s.contains("H"),s-> s.contains("w"));
        System.out.println("邏輯或的結(jié)果:"+isValid);
    }

    private static void doTest(Predicate<String> predicate) {
        boolean veryLong = predicate.test("Hello World");
        System.out.println("字符串長(zhǎng)度很長(zhǎng)嗎:" + veryLong);
    }

    private static boolean doAnd(Predicate<String> resource, Predicate<String> target) {
        boolean isValid = resource.and(target).test("Hello world");
        return isValid;
    }

    private static boolean doOr(Predicate<String> one, Predicate<String> two) {
        boolean isValid = one.or(two).test("Hello world");
        return isValid;
    }
    private static void doNegate(Predicate<String> predicate) {
        boolean veryLong = predicate.negate().test("Hello World");
        System.out.println("字符串長(zhǎng)度很長(zhǎng)嗎:" + veryLong);
    }
}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

結(jié)果如下:

字符串長(zhǎng)度很長(zhǎng)嗎:true
字符串長(zhǎng)度很長(zhǎng)嗎:false
邏輯與的結(jié)果:true
邏輯或的結(jié)果:true

3.2 Supplier

用來(lái)獲取一個(gè)泛型參數(shù)指定類型的對(duì)象數(shù)據(jù)(生產(chǎn)一個(gè)數(shù)據(jù)),我們可以把它理解為一個(gè)工廠類,用來(lái)創(chuàng)建對(duì)象。

Supplier 接口包含一個(gè)抽象方法 get,通常我們它來(lái)做對(duì)象轉(zhuǎn)換。

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
import java.util.function.Supplier;

public class DemoSupplier {
    public static void main(String[] args) {
        String sA = "Hello ";
        String sB = "World ";
        System.out.println(
                getString(
                        () -> sA + sB
                )
        );
    }

    private static String getString(Supplier<String> stringSupplier) {
        return stringSupplier.get();
    }
}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

結(jié)果如下:

Hello World 

上述例子中,我們把兩個(gè) String 對(duì)象合并成一個(gè) String。

3.3 Consumer

與 Supplier 接口相反,Consumer 接口用于消費(fèi)一個(gè)數(shù)據(jù)。

Consumer 接口包含一個(gè)抽象方法 accept 以及默認(rèn)方法 andThen 這樣 Consumer 接口可以通過(guò) andThen 來(lái)進(jìn)行組合滿足我們不同的數(shù)據(jù)消費(fèi)需求。最常用的 Consumer 接口就是我們的 for 循環(huán),for 循環(huán)里面的代碼內(nèi)容就是一個(gè) Consumer 對(duì)象的內(nèi)容。

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
import java.util.function.Consumer;

public class DemoConsumer {
    public static void main(String[] args) {
        //調(diào)用默認(rèn)方法
        consumerString(s -> System.out.println(s));
        //consumer接口的組合
        consumerString(
                // toUpperCase()方法,將字符串轉(zhuǎn)換為大寫
                s -> System.out.println(s.toUpperCase()),
                // toLowerCase()方法,將字符串轉(zhuǎn)換為小寫
                s -> System.out.println(s.toLowerCase())
        );
    }

    private static void consumerString(Consumer<String> consumer) {
        consumer.accept("Hello");
    }

    private static void consumerString(Consumer<String> first, Consumer<String> second) {
        first.andThen(second).accept("Hello");
    }
}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

結(jié)果如下:

Hello
HELLO
hello

在調(diào)用第二個(gè) consumerString 的時(shí)候我們通過(guò) andThen 把兩個(gè) Consumer 組合起來(lái),首先把 Hello 全部轉(zhuǎn)變成大寫,然后再全部轉(zhuǎn)變成小寫。

3.4 Function

根據(jù)一個(gè)類型的數(shù)據(jù)得到另一個(gè)類型的數(shù)據(jù),換言之,根據(jù)輸入得到輸出。

Function 接口有一個(gè)抽象方法 apply 和默認(rèn)方法 andThen,通過(guò) andThen 可以把多個(gè) Function 接口進(jìn)行組合,是適用范圍最廣的函數(shù)接口。

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
import java.util.function.Function;

public class DemoFunction {
    public static void main(String[] args) {
        doApply(s -> Integer.parseInt(s));
        doCombine(
                str -> Integer.parseInt(str)+10,
                i -> i *= 10
        );
    }

    private static void doApply(Function<String, Integer> function) {
        int num = function.apply("10");
        System.out.println(num + 20);
    }
    private static void doCombine(Function<String, Integer> first, Function<Integer, Integer> second) {
        int num = first.andThen(second).apply("10");
        System.out.println(num + 20);
    }
}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

結(jié)果如下:

30
220

上述四個(gè)函數(shù)接口是最基本最常用的函數(shù)接口,需要熟悉其相應(yīng)的使用場(chǎng)景并能夠熟練使用。 UnaryOperatorBinaryOperator 作用與 Funciton 類似,大家可以通過(guò) Java 的源代碼進(jìn)一步了解其作用。

4. 小結(jié)

本節(jié),我們主要闡述了函數(shù)式接口的定義以及其與 Lambda 表達(dá)式的關(guān)系。并對(duì)新增的 java.util.function 包中常用的函數(shù)式接口進(jìn)行了解釋。這些接口常用于集合處理中(我們將在后續(xù)的內(nèi)容進(jìn)一步學(xué)習(xí)),關(guān)于函數(shù)式接口主要記住一點(diǎn),那就是:

接口有且僅有一個(gè)抽象方法