下面這些 interface,全世界各地的 Java 開發人員至少用過一個以上:
java.lang.Runnable
、java.awt.event.ActionListener
、
java.util.Comparator
、java.util.concurrent.Callable
。
上述這些 interface 當中有一個共同的特點,就是它們只定義了一個 method。
JDK 當中有一堆這樣的 interface、Java 開發人員也製造了一堆。
這些 interface 也被稱為 Single Abstract Method interface(SAM interface)。
普遍常見的用法是產生一個 anonymous inner class 來使用這些 interface:
public class AnonymousInnerClassTest {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("A thread created and running ...");
}
}).start();
}
}
在 Java 8 當中,SAM interface 的概念被重新製作,取名叫作 functional interface。 method reference 跟 constructor reference 可以用 lambda expression 來呈現 (我接下來的 blog 文章會涵蓋這兩個主題)。 在這裡導入了一個 annotation:@FunctionalInterface, 當你在一個不是 functional interface 的 interface 用這個 annotation, compiler 就會炸錯誤。 讓我們來看一下一個簡單的 functional interface,裡頭只有一個 abstract method:
@FunctionalInterface
public interface SimpleFuncInterface {
public void doWork();
}
這個 interface 也可以把 java.lang.Object
的 method 宣告成 abstract method,
但依然是個 functional interface:
@FunctionalInterface
public interface SimpleFuncInterface {
public void doWork();
public String toString();
public boolean equals(Object o);
}
一旦你加了另一個 abstract method 進去,compiler 或是 IDE 就會標示錯誤, 像下面這張圖這樣:
interface 如果繼承另一個 functional interface, 而且沒有宣告任何新的 abstract method, 那麼新的 interface 仍然是 functional interface。 另一種情況是 interface 當中如果有一個 abstract method、 以及任意數量的 default method, 這個 interface 依然是 functional interface。 想了解 default method 可以看這篇文章。
@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface {
default public void doSomeWork(){
System.out.println("Doing some work in interface impl...");
}
default public void doSomeOtherWork(){
System.out.println("Doing some other work in interface impl...");
}
}
上面這個 interface 仍然是一個有效的 functional interface。 現在我們來看看如何用 lambda expression 實作 function interface, 做出 anonymous inner class 的效果:
/*
* 比對用 anonymous inner class 以及 lambda expression 的實作方式
*/
public class SimpleFunInterfaceTest {
public static void main(String[] args) {
carryOutWork(new SimpleFuncInterface() {
@Override
public void doWork() {
System.out.println("Do work in SimpleFun impl...");
}
});
carryOutWork(() -> System.out.println("Do work in lambda exp impl..."));
}
public static void carryOutWork(SimpleFuncInterface sfi){
sfi.doWork();
}
}
程式輸出會長這樣:
Do work in SimpleFun impl...
Do work in lambda exp impl...
如果你用有支援 Java lambda expression 語法的 IDE(Netbeans 8 Nightly build), 那麼以上面的例子來說,會在 anonymous inner class 提供一個提示訊息:
這篇文章簡單地介紹了 Java 8 當中 functional interface 的觀念, 以及如何用 lambda expression 實作。
沒有留言:
張貼留言