什么是函數式接口
函數式接口是Java8引用的一個新特性,是一種特殊的接口:SAM類型的接口(Single Abstract Method)。但是它還是一個接口,只是有些特殊罷了。 函數式接口的出現主要是為了配合Java8的另一個新特性Lamdba表達式來使用。
- 接口中只有一個抽象方法
- 接口中面可以加一個注解@FunctionalInterface來檢查接口中的方法是不是只有一個抽象方法
- 在接口里面可以加入 默認方法 和 靜態方法
- 函數式接口也可以繼承,但是繼承的時候,抽象方法必須一樣
- 函數式接口重寫父類的的方法,並不會計入到自己的抽象方法中
自定義函數式接口
//加入這個注解是為了檢測接口中是否符合函數式接口的要求
@FunctionalInterface
public interface MyFunctionInterction {
//唯一的抽象方法
void absoluMethod();
//重寫Object的方法
@Override
String toString();
//默認方法
default void defaultMethod() {
System.out.println("默認方法");
}
//靜態方法
static void stativMethod() {
System.out.println("靜態方法");
}
}
函數式接口的簡單使用
里面的默認方法可以直接使用
public class TestFunctionIntection {
public static void main(String[] args) {
TestFunctionIntection testFunctionIntection =
new TestFunctionIntection();
testFunctionIntection.test(
//Lamdba表達式的簡單使用
() -> System.out.println("函數式接口里面的抽象方法"));
}
/**
* 自己定義的一個方法,並使用自定義的一個消費類型的函數式接口
* @param myFunctionInterction
*/
public void test(MyFunctionInterction
myFunctionInterction) {
//函數式接口里面的抽象方法
myFunctionInterction.absoluMethod();
//默認方法
myFunctionInterction.defaultMethod();
//靜態方法
MyFunctionInterction.stativMethod();
}
}
java8里面自定義的四個核心的函數式接口
上面我自定義的一個接口,就是一個消費類型的函數式接口。其實這類接口在java.util.function里面有定義的,就是void Consumer< T >,消費類型接口,上面代碼中的test方法里面的接口其實可以換成Consumer< T >接口,也可以用,下面主要就是介紹這四個函數式接口的簡單使用。
下面是這四個核心接口的簡單使用
public class FunctionTest {
//Consumer<T> 消費型接口
@Test
public void test1() {
Consumer<String> consumer = (x) -> System.out.println(x);
consumer.accept("消費型接口,沒有返回值!");
}
//輸出:消費型接口,沒有返回值!
//供給型接口
@Test
public void test2() {
Supplier<String> supplier = () -> "主要的作用就是創建對象!";
String s = supplier.get();
System.out.println(s);
}
//輸出:主要的作用就是創建對象!
//函數型接口
//Function<T,R> T 接收的參數,R 返回值類型
@Test
public void test3() {
Function<Integer, String> function = (x) -> x + ":為String類型";
String apply = function.apply(7);
System.out.println(apply);
}
//輸出:7:為String類型
//斷言型接口
@Test
public void test4() {
Predicate<Integer> predicate = (x) -> x > 10;
boolean test = predicate.test(11);
System.out.println(test);
}
//輸出:true
}
Consumer
的應用
//Consumer<T> 消費型接口
@Test
public void test1() {
//定義一個消費型接口,只輸出輸入的內容
Consumer<String> consumer = (x) -> System.out.println(x);
//在輸入的內容后面加上·--加上了默認方法·
Consumer<String> consumer2 = (x) -> System.out.println(x + "--加上了默認方法");
//執行順序 先執行 accept 后面執行 addThen(然后)
consumer.andThen(consumer2).accept("消費型接口,沒有返回值!");
}
//輸出:消費型接口,沒有返回值 (accept輸出的值)
//輸出:消費型接口,沒有返回值 !--加上了默認方法 (addThen輸出的值)
Consumer
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
其返回值這一句是重點,先是傳入一個Consumer接口,然后返回一個Consumer接口,說明可以用表達式鏈,然后用這個特性可以把數據進一次進行加工。
(T t) -> { accept(t); after.accept(t); };這一句,返回的順序首先是調用抽象方法,然后再調用默認方法,說明這個默認方法只可以對數據進行再加工,不能再抽象方法前面。
Supplier
的應用
//供給型接口,這個方法若以用在工廠方法中
@Test
public void test2() {
//跟據一個字符串創建對象
Supplier<String> supplier = () -> "主要的作用就是創建對象!";
//獲取一個對象
String s = supplier.get();
//獲取兩個以象
String s1 = supplier.get();
//兩個對象內容一樣
System.out.println(s.equals(s1));
System.out.println(s);
//用方法引用的方式創建一個對象
Supplier<SupplierTest> testSupplier = SupplierTest::new;
//用new的方式創建一個對象
Supplier<SupplierTest> supplierTestSupplier = () -> new SupplierTest("張三");
//可以通過supplierTestSupplier 來獲取一個對象,並且可以調用里面的方法
String name = supplierTestSupplier.get().getName();
System.out.println(name);
}
//輸出:true
//輸出:主要的作用就是創建對象!
//輸出:張三
Supplier< T >接口類型就有一個方法簽名。T get()方法,沒有默認方法。
Function< T,R > 的應用
//默認主法addThen
//函數型接口
//Function<T,R> T 接收的參數,R 返回值類型
@Test
public void test3() {
Function<String, String> f1 = (x) -> x +"+ ";
Function<String, String> f2 = (x) -> x + "- ";
//addThen(然后的意思)執行順序先執行f1,並且把執行后的結果作為f2的輸入參數
String apply = f1.andThen(f2).apply("1");
System.out.println(apply);
}
//輸出:1+ -
addThen的源碼:
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
源碼中最重要的一句
(V v) -> apply(before.apply(v)); 規定了執行順序
//默認主法compose
//函數型接口
//Function<T,R> T 接收的參數,R 返回值類型
@Test
public void test3() {
Function<String, String> f1 = (x) -> x +"+ ";
Function<String, String> f2 = (x) -> x + "- ";
//addThen(然后的意思)執行順序先執行f2,並且把執行后的結果作為f1的輸入參數
String apply = f1.compose(f2).apply("1");
System.out.println(apply);
}
//輸出:1- +
三個默認方法,但是最后一個用的不多,這里也就不再介紹了。
Predicate< T > 的應用
//默主方法negate 非
//斷言型接口
@Test
public void test4() {
Predicate<Integer> predicate = (x) -> x > 10;
boolean test = predicate.negate().test(11);
System.out.println(test);
}
//輸出:false
//斷言型接口
//默認方法 or 和 and
@Test
public void test4() {
Predicate<Integer> p1 = (x) -> x > 10;
Predicate<Integer> p2 = (x) -> x < 5;
//默認方法 or 或
boolean test = p1.or(p2).test(3);
//默認方法 and 且
boolean test2 = p1.and(p2).test(3);
System.out.println(test);
System.out.println(test2);
}
//輸出:true
//輸出:false
函數式接口的使用
函數式接口的的使用,大部分都是在流操作里面進行,現在可以不太理解,但是可以在學習完流操作以后,再過來看,並且跟着寫一遍。代碼光看是沒有用的。如果不寫是不知道意思的。
參考的博客:淺淺的函數式接口
細節決定成敗!
個人愚見,如有不對,懇請扶正!