JDK8 新特性 java.util.function Function介面
阿新 • • 發佈:2019-01-02
參考部落格 : JDK8新特性-java.util.function-Function介面
原始碼(刪除了原始碼註釋):
package java.util.function; import java.util.Objects; @FunctionalInterface public interface Function<T, R> { R apply(T t); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } static <T> Function<T, T> identity() { return t -> t; } }
標註為 @FunctionalInterface 的介面被稱為函式式介面,該介面只能有一個抽象方法。如果一個介面只有一個抽象方法,則編譯器會認為這就是一個函式式介面。是否是一個函式式介面,需要注意的有以下幾點:
- 該註解只能標記在”有且僅有一個抽象方法”的介面上。
- JDK8 介面中的靜態方法和預設方法,都不是抽象方法。
- 介面預設繼承 java.lang.Object,所以如果介面顯示宣告覆蓋了 Object 中的方法,那麼也不算抽象方法。
- 該註解不是必須的,如果一個介面符合”函式式介面”定義,那麼加不加該註解都沒有影響。加上該註解能夠更好地讓編譯器進行檢查。如果編寫的不是函式式介面(比如有多個抽象方法),但是加上了@FunctionInterface,那麼編譯器會報錯。
報錯如下圖:
報錯程式碼如下:
package test;
import java.util.function.Function;
@FunctionalInterface
public interface myFunction extends Function<String , Integer> {
Integer testFunctionalInterface();
}
因為 myFunction 介面繼承了 Function 介面,Function 接口裡面本來就定義了一個 apply() 抽象方法,因為 myFunction 介面又定義了一個抽象方法,所以不符合”函式式介面”定義了,加上 @FunctionalInterface,就會報錯。
使用 Function 介面:
- 使用 lambda 表示式直接賦值
Function<String , Integer> get_length = (String s) -> {
return s.length();
};
Function<String , String> append = (String s) -> s.concat(" kaven!");
- 匿名類實現
Function<Integer , Integer> add = new Function<Integer, Integer>() {
@Override
public Integer apply(Integer integer) {
return integer+100;
}
};
生成的 class 程式碼如下圖:
我覺得兩種方式都是給 Function 介面的 apply() 抽象方法進行定義。
測試程式碼如下:
package test;
import java.util.function.Function;
public class testFunction {
public static void main(String[] args){
Function<String , Integer> get_length = (String s) -> {
return s.length();
};
Function<String , String> append = (String s) -> s.concat(" kaven!");
System.out.println(append.apply("Welcome"));
System.out.println(get_length.compose(append).apply("Welcome"));
System.out.println(append.andThen(get_length).apply("Welcome"));
Function<Integer , Integer> add = new Function<Integer, Integer>() {
@Override
public Integer apply(Integer integer) {
return integer+100;
}
};
System.out.println(add.apply(100));
System.out.println(Function.identity().apply("Kaven"));
}
}
輸出資料如下:
Welcome kaven!
14
14
200
Kaven
System.out.println(get_length.compose(append).apply("Welcome"));
System.out.println(append.andThen(get_length).apply("Welcome"));
這兩行程式碼的效果是一樣的,先呼叫 append 的 apply() 方法,後呼叫get_length 的 apply() 方法。
原始碼也可以看出來:
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));//先呼叫 before 的 apply() 方法,後呼叫 this 的 apply() 方法。
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));//先呼叫 this 的 apply() 方法,後呼叫 after 的 apply() 方法。
}
static <T> Function<T, T> identity() {
return t -> t;
}
Function 介面的靜態方法,返回一個 Function<T, T> 例項,並且給這個例項的 apply() 抽象方法賦值了一個 lambda 表示式 t -> t。所以呼叫 apply(“Kaven”),就會輸出 Kaven。
Function 介面可以搭配 BiFunction 介面一起使用(看原始碼就很清楚了,也刪除了原始碼註釋):
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
}
}