java interface 函数_java8函数式接口(Functional Interface)
介紹
函數(shù)式接口(Functional Interface)就是一個有且僅有一個抽象方法,但是可以有多個非抽象方法的接口。
函數(shù)式接口可以被隱式轉(zhuǎn)換為 lambda 表達(dá)式(箭頭函數(shù))。
函數(shù)式接口代表的一種契約, 一種對某個特定函數(shù)類型的契約。
Lambda表達(dá)式不能脫離上下文而存在,它必須要有一個明確的目標(biāo)類型(interface),而這個目標(biāo)類型就是某個函數(shù)式接口。
java8之前已經(jīng)存在的函數(shù)式接口有很多,比如java.lang.Runnable、java.util.concurrent.Callable、java.util.Comparator等。
而新增加的函數(shù)式接口都在java.util.function包下。
Java 不會強(qiáng)制要求你使用 @FunctionalInterface 注解來標(biāo)記你的接口是函數(shù)式接口, 然而,作為API作者, 你可能傾向使用@FunctionalInterface指明特定的接口為函數(shù)式接口, 這只是一個設(shè)計(jì)上的考慮, 可以讓用戶很明顯的知道一個接口是函數(shù)式接口。
入門
先來看一個入門的例子就能明白為啥函數(shù)式接口是一種契約:
@FunctionalInterface
public interface Predicate {
//該接口有一個抽象方法test,它接受一個參數(shù)t,并且返回boolean
//如此定義一個抽象方法,就是在約定,我這個抽象方法的實(shí)現(xiàn)類,一定是僅有一個參數(shù),并且只會返回一個boolean的值。
//所以說函數(shù)式接口是一種契約。
boolean test(T t);
}
Predicate的使用實(shí)例:
//方法evel接受一個列表和一個Predicate接口
//list每個元素會當(dāng)成 predicate的test方法的參數(shù)。
//因?yàn)楹瘮?shù)式接口是可以使用Lambda表達(dá)式的,所以第二個參數(shù)這里就可以使用箭頭函數(shù)了。
public static void eval(List list, Predicate predicate) {
//循環(huán)list
for(Integer i: list) {
//調(diào)用predicate的test方法,返回一個boolean值。
if(predicate.test(i)) {
System.out.println(i + " ");
}
//疑問:Predicate是一個接口啊!那他具體執(zhí)行的方法(實(shí)現(xiàn)類/實(shí)現(xiàn)方法)在哪里呢????
//請看main方法!!!
}
}
public static void main(String args[]){
//定義一個list
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
//n -> n%2
//其實(shí)很簡單,這個Lambda表達(dá)式其實(shí)就是Predicate接口的實(shí)現(xiàn):
// 箭頭左邊 n 是一個參數(shù), 它會被傳遞到 Predicate 接口的 test 方法中
// 而箭頭右邊 n%2 其實(shí)就是這個 test 抽象方法的實(shí)現(xiàn)方法,它用來計(jì)算輸入?yún)?shù)是否是一個偶數(shù)。
//所以整個方法就是用來打印list中的偶數(shù)了。
eval(list, n-> n%2 == 0 );
System.out.println("輸出所有偶數(shù):");
}
新函數(shù)式接口
java.util.function中定義了幾組類型的函數(shù)式接口以及針對基本數(shù)據(jù)類型的子接口。
Predicate -- 傳入一個參數(shù),返回一個bool結(jié)果, 方法為boolean test(T t)
Consumer -- 傳入一個參數(shù),無返回值,純消費(fèi)。 方法為void accept(T t)
Function -- 傳入一個參數(shù),返回一個結(jié)果,方法為R apply(T t)
Supplier -- 無參數(shù)傳入,返回一個結(jié)果,方法為T get()
UnaryOperator -- 一元操作符, 繼承Function,傳入?yún)?shù)的類型和返回類型相同。
BinaryOperator -- 二元操作符, 傳入的兩個參數(shù)的類型和返回類型相同, 繼承BiFunction
函數(shù)式接口中的抽象方法
在上面介紹中,說到函數(shù)式接口有且僅有一個抽象方法,其實(shí)是不正確的,因?yàn)楹瘮?shù)式接口中可以額外定義多個抽象方法,但這些抽象方法簽名必須和Object類的public方法一樣,只是我們一般不會再重新定義這些方法。
@FunctionalInterface
public interface ObjectMethodFunctionalInterface {
void count(int i);
String toString(); //same to Object.toString
int hashCode(); //same to Object.hashCode
boolean equals(Object obj); //same to Object.equals
}
聲明異常
函數(shù)式接口的抽象方法可以聲明 可檢查異常(checked exception)。 在調(diào)用目標(biāo)對象的這個方法時必須catch這個異常。
@FunctionalInterface
interface InterfaceWithException {
//聲明異常
void apply(int i) throws Exception;
}
捕獲異常:
public class FunctionalInterfaceWithException {
public static void main(String[] args) {
InterfaceWithException target = i -> {};
try {
target.apply(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
非法拋出異常:
@FunctionalInterface
interface InterfaceWithException {
//沒有聲明異常
void apply(int i);
}
public class FunctionalInterfaceWithException {
public static void main(String[] args) {
//函數(shù)式接口沒有聲明異常,
//而 Lambda中卻拋出了異常,此時是無法通過編譯的!!!
InterfaceWithException target = i -> {throw new Exception();};
}
}
靜態(tài)方法
函數(shù)式接口中除了那個抽象方法外還可以包含靜態(tài)方法。
Java 8以前的規(guī)范中接口中不允許定義靜態(tài)方法。 靜態(tài)方法只能在類中定義。 但是到了Java 8,可以定義靜態(tài)方法。
默認(rèn)方法
Java 8中允許接口實(shí)現(xiàn)方法, 而不是簡單的聲明, 這些方法叫做默認(rèn)方法,使用特殊的關(guān)鍵字default。
因?yàn)槟J(rèn)方法不是抽象方法,所以不影響我們判斷一個接口是否是函數(shù)式接口。
function包中的類的函數(shù)式接口概覽
BiConsumer 代表了一個接受兩個輸入?yún)?shù)的操作,并且不返回任何結(jié)果
BiFunction 代表了一個接受兩個輸入?yún)?shù)的方法,并且返回一個結(jié)果
BinaryOperator 代表了一個作用于于兩個同類型操作符的操作,并且返回了操作符同類型的結(jié)果
BiPredicate 代表了一個兩個參數(shù)的boolean值方法
BooleanSupplier 代表了boolean值結(jié)果的提供方
Consumer 代表了接受一個輸入?yún)?shù)并且無返回的操作
DoubleBinaryOperator 代表了作用于兩個double值操作符的操作,并且返回了一個double值的結(jié)果。
DoubleConsumer 代表一個接受double值參數(shù)的操作,并且不返回結(jié)果。
DoubleFunction 代表接受一個double值參數(shù)的方法,并且返回結(jié)果
DoublePredicate 代表一個擁有double值參數(shù)的boolean值方法
DoubleSupplier 代表一個double值結(jié)構(gòu)的提供方
DoubleToIntFunction 接受一個double類型輸入,返回一個int類型結(jié)果。
DoubleToLongFunction 接受一個double類型輸入,返回一個long類型結(jié)果
DoubleUnaryOperator 接受一個參數(shù)同為類型double,返回值類型也為double 。
Function 接受一個輸入?yún)?shù),返回一個結(jié)果。
IntBinaryOperator 接受兩個參數(shù)同為類型int,返回值類型也為int 。
IntConsumer 接受一個int類型的輸入?yún)?shù),無返回值 。
IntFunction 接受一個int類型輸入?yún)?shù),返回一個結(jié)果 。
IntPredicate :接受一個int輸入?yún)?shù),返回一個布爾值的結(jié)果。
IntSupplier 無參數(shù),返回一個int類型結(jié)果。
IntToDoubleFunction 接受一個int類型輸入,返回一個double類型結(jié)果 。
IntToLongFunction 接受一個int類型輸入,返回一個long類型結(jié)果。
IntUnaryOperator 接受一個參數(shù)同為類型int,返回值類型也為int 。
LongBinaryOperator 接受兩個參數(shù)同為類型long,返回值類型也為long。
LongConsumer 接受一個long類型的輸入?yún)?shù),無返回值。
LongFunction 接受一個long類型輸入?yún)?shù),返回一個結(jié)果。
LongPredicate R接受一個long輸入?yún)?shù),返回一個布爾值類型結(jié)果。
LongSupplier 無參數(shù),返回一個結(jié)果long類型的值。
LongToDoubleFunction 接受一個long類型輸入,返回一個double類型結(jié)果。
LongToIntFunction 接受一個long類型輸入,返回一個int類型結(jié)果。
LongUnaryOperator 接受一個參數(shù)同為類型long,返回值類型也為long。
ObjDoubleConsumer 接受一個object類型和一個double類型的輸入?yún)?shù),無返回值。
ObjIntConsumer 接受一個object類型和一個int類型的輸入?yún)?shù),無返回值。
ObjLongConsumer 接受一個object類型和一個long類型的輸入?yún)?shù),無返回值。
Predicate 接受一個輸入?yún)?shù),返回一個布爾值結(jié)果。
Supplier 無參數(shù),返回一個結(jié)果。
ToDoubleBiFunction 接受兩個輸入?yún)?shù),返回一個double類型結(jié)果
ToDoubleFunction 接受一個輸入?yún)?shù),返回一個double類型結(jié)果
ToIntBiFunction 接受兩個輸入?yún)?shù),返回一個int類型結(jié)果。
ToIntFunction 接受一個輸入?yún)?shù),返回一個int類型結(jié)果。
ToLongBiFunction 接受兩個輸入?yún)?shù),返回一個long類型結(jié)果。
ToLongFunction 接受一個輸入?yún)?shù),返回一個long類型結(jié)果。
UnaryOperator 接受一個參數(shù)為類型T,返回值類型也為T
總結(jié)
以上是生活随笔為你收集整理的java interface 函数_java8函数式接口(Functional Interface)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宝马电子快排是单向还是双向
- 下一篇: 光瓶粮食酒有哪几种?哪种性价比高?