Java 8 - Functional Interface 函數式接口
Overview
函數式接口(Functional interface)是那些有,且只有顯示定義一個方法的接口。
函數式接口可以被隱式轉換為lambda表達式。
範例:
public interface MyFunctionalInterface {
public void execute();
}
The above counts as a functional interface in Java because it only contains a single method, and that method has no implementation. Normally a Java interface does not contain implementation of the methods it declares, but it can contain implementation in default methods, or in static methods. Below is another example of a Java functional interface, with implementations of some of the methods.
能成為函數式接口(functional interface)的情況:
- 只有一個方法,並且該方法沒有被實作
可以包含的方法,也就是不影響函數式接口:
- default method(s)
- static method(s)
- public method(s) instanceof Object class
不成立函數式接口的情況:
- 有多個一般方法
- 繼承的
Object
方法不是public
public interface MyFunctionalInterface {
/**
* only contains a signal method in interface is functional interface
*/
public void execute();
/**
* default method is acceptable in functional interface
*
* @param text use string param to do sth
*/
public default void print(String text) {
// do sth
}
/**
* static method is also acceptable in functional interface
*
* @param i use int param i to do sth
*/
public static void print(int i) {
// do sth
}
/**
* methods that are instance Object class, note: must be public method in Object
*
* @return Object
*/
@Override
String toString();
@Override
int hashCode();
@Override
boolean equals(Object object);
/**
* if there have some methods that is not public of Object class,
* it is not functional interface. for example, clone() method is
* protected modifier inside Object class instead of public.
*
* @return Object
*/
Object clone();
}
Reason
为什么会单单从接口中定义出此类接口呢?原因是在Java Lambda的实现中, 开发组不想再为Lambda表达式单独定义 一种特殊的Structural函数类型,称之为箭头类型(arrow type), 依然想采用Java既有的类型系统(class, interface, method等), 原因是增加一个结构化的函数类型会增加函数类型的复杂性,破坏既有的Java类型,并对成千上万的Java类库造成严重的影响。 权衡利弊,因此最终还是利用SAM接口作为Lambda表达式的目标类型。
@FunctionalInterface
此註解功能類似於@Override
,可以幫助我們檢查是否為函數式接口(functional interface),如果不符合定義就會編譯報錯。
例如以上述代碼為例:
@FunctionalInterface
public interface MyFunctionalInterface {
public void execute();
public default void print(String text) {
// do sth
}
public static void print(int i) {
// do sth
}
@Override
String toString();
@Override
int hashCode();
@Override
boolean equals(Object object);
}
在上述代碼中,並未有:
- 一個以上的一般方法
- 非
public
的Object class
方法
原因是可以保護函數式接口能成功轉換為lambda表達式,如果想要通過lambda表達式來實作此接口,請添加此安全性注釋。
如果改成以下這樣,就會報錯:
@FunctionalInterface
public interface MyFunctionalInterface {
public void execute();
public void secondExecute();
}
或是:
@FunctionalInterface
public interface MyFunctionalInterface {
public void execute();
Object clone();
}
錯誤訊息為:
Multiple non-override abstract methods found in interface
Ref:
- FunctionalInterface (Java Platform SE 8 )
- lambda - What are functional interfaces used for in Java 8? - Stack Overflow
- functional interface - Why to use @FunctionalInterface annotation in Java 8 - Stack Overflow