標籤:interface object default java public
引言
目前由於系統已經全面切換為JDK8,所以有必要系統的瞭解一下Java8的一些新特性,以便後續在日常工作中可以使用一些進階特性來提高編程效率。
因為Java8引入了函數式介面,在java.util.function包含了幾大類函數式介面聲明。這裡第一篇主要研究一下Function相關的介面。
FunctionalInterface註解
Java8的新引入,包含函數式的設計,介面都有@FunctionalInterface的註解。就像這個註解的注釋說明一樣,它註解在介面層面,且註解的介面要有且僅有一個抽象方法。具體就是說,註解在Inteface上,且interface裡只能有一個抽象方法,可以有default方法。因為從語義上來講,一個函數式介面需要通過一個***邏輯上的***方法表達一個單一函數。那理解這個單一就很重要了,單一不是說限制你一個interface裡只有一個抽象方法,單是多個方法的其他方法需要是繼承自Object的public方法,或者你要想繞過,就自己實現default。函數式介面自己本身一定是只有一個抽象方法。同時,如果是Object類的public方法,也是不允許的。官方的說明翻譯如下:
如果一個介面I,I有一組抽象方法集合M,且這些方法都不是Object類的public簽名方法,那麼如果存在一個M中的方法m,滿足:
怎麼理解,看幾個例子。
比如:你聲明一個介面:
@FunctionalInterfacepublic interface Func {}
這會編譯錯,編譯器會告訴你*no target method*。而如果加一個方法:
@FunctionalInterfacepublic interface Func { void run();}
這就OK了,一個函數式介面聲明好了。再加一個呢?
@FunctionalInterfacepublic interface Func { void run(); void foo();}
不ok,明確說了只有一個抽象方法嘛。但是如果換一種函數簽名:
@FunctionalInterfacepublic interface Func { boolean equals(Object obj);}
錯誤依舊,因為這個方法簽名是Object類的public方法。而再改一下:
@FunctionalInterfacepublic interface Func { boolean equals(Object obj); void run();}
這就OK了。一個抽象方法,一個Object的public方法,相安無事。Object還有其他方法,clone方法試試會怎麼樣?
@FunctionalInterfacepublic interface Func { Object clone(); void run();}
這又不行了,因為前面明確說了,要是Object的public方法,而clone是protected的。
所以總結一句話就是:
函數式介面,有且僅有一個抽象方法,Object的public方法除外。
因為Java本身支援多介面實現,你定義一個Class可以implements多個interface。所以這個限制也沒什麼影響,如果想約定一個函數式介面來統一,也可以做一些預設的實現來達到一個介面多個抽象方法的目的,比如下面這種做法:
一個普通介面NonFunc:
public interface NonFunc { void foo(); void voo();}
函數式介面Func:
@FunctionalInterfacepublic interface Func extends NonFunc { void run(); default void foo() { // do something } default void voo() { // do something }}
實現的測試類別:
public class TestJ8FunctionalInterface implements Func { public static void main(String[] args) { Func func = new TestJ8FunctionalInterface(); func.run(); func.foo(); func.voo(); } @Override public void run() { System.out.println("run"); } @Override public void foo() { System.out.println("foo"); } @Override public void voo() { System.out.println("voo"); }}
函數式介面的一大特性就是可以被lambda運算式和函數參考資料表達式代替。也就是說聲明這樣的介面,是可以靈活的以方法來傳參。看個例子:
public class TestJ8FunctionalInterface2 { public static void main(String[] args) { TestJ8FunctionalInterface2 testJ8FunctionalInterface2 = new TestJ8FunctionalInterface2(); // lambda testJ8FunctionalInterface2.test(10, () -> System.out.println("A customed Func.")); // method reference testJ8FunctionalInterface2.test(100, testJ8FunctionalInterface2::customedFunc); } public void customedFunc() { System.out.println("A customed method reference."); } public void test(int x, Func func) { System.out.println(x); func.run(); }}
上面例子列舉了一個lambda模式和一個方法參考模式,這樣就可以利用函數式編程強大的能力,將方法作為參數了。
閱讀全文請點擊:http://click.aliyun.com/m/9152/
本文出自 “12466150” 部落格,請務必保留此出處http://12476150.blog.51cto.com/12466150/1890430
【Java系列教程】一起爪哇Java 8(一)——函數式介面