函数式编程是 java 8 的新特性,lambda 表达式中用到了很多函数式接口。比如 Runnable 接口 :
public class Mytest {
public static void main(String[] args) {
new Thread( ()-> System.out.println( Thread.currentThread() +" is running ...")
).start();
}
}
下面是 Runnable 接口的源代码。我们可以看到 @FunctionalInterface 注解修饰了 Runnable 接口。
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
下面是 @FunctionalInterface 注解的源码。
第一段表示,该注解修饰的接口是函数式接口。
第二段表示,一个函数式接口有且仅有一个抽象方法。1.接口中的default 实例方法 不是抽象方法。 2. java.lang.Object 中的方法 在接口中重写,也不能算作 抽象方法。因为该接口的实现类中都会有 java.lang.Object 的实例方法。
第三段表示,可以通过 lambda 表达式、方法引用、构造方法引用 来创建 函数式接口 的实例。
第四段表示。1.该注解无法用于修饰 注解(@interface)、enum(枚举)、class(普通java类)。
2.该注解修饰的接口,必须满足函数式接口的要求。(具体要求在第二段)。
第五段表示,不管接口声明上是否有@FunctionInterface 注解,编译器都会自动将满足条件的接口作为函数式接口。
/**
* An informative annotation type used to indicate that an interface
* type declaration is intended to be a <i>functional interface</i> as
* defined by the Java Language Specification.
*
* Conceptually, a functional interface has exactly one abstract
* method. Since {@linkplain java.lang.reflect.Method#isDefault()
* default methods} have an implementation, they are not abstract. If
* an interface declares an abstract method overriding one of the
* public methods of {@code java.lang.Object}, that also does
* <em>not</em> count toward the interface's abstract method count
* since any implementation of the interface will have an
* implementation from {@code java.lang.Object} or elsewhere.
*
* <p>Note that instances of functional interfaces can be created with
* lambda expressions, method references, or constructor references.
*
* <p>If a type is annotated with this annotation type, compilers are
* required to generate an error message unless:
*
* <ul>
* <li> The type is an interface type and not an annotation type, enum, or class.
* <li> The annotated type satisfies the requirements of a functional interface.
* </ul>
*
* <p>However, the compiler will treat any interface meeting the
* definition of a functional interface as a functional interface
* regardless of whether or not a {@code FunctionalInterface}
* annotation is present on the interface declaration.
*
* @jls 4.3.2. The Class Object
* @jls 9.8 Functional Interfaces
* @jls 9.4.3 Interface Method Body
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
接下来,我们再来看看 JDK 提供的一些常用函数式接口。java.util.function 包下面有一些 Stream 流操作用到的函数式接口。
下面我们利用注解@FunctionInterface 来实现一个自定义的函数式接口
//@FunctionalInterface //可以省略
public interface MySayInterface {
void say(String content);
}
我们再写一段测试代码。
public class Mytest {
public static void main(String[] args) {
/* new Thread( ()-> System.out.println( Thread.currentThread() +" is running ...") ).start();
MySayInterface sayInterface = new MySayInterface() {
@Override
public void say(String content) {
System.out.println( content );
}
}; */
MySayInterface sayInterface =(content )-> System.out.println( content );
sayInterface.say(" functional interface ");
}
}
我们来看看运行效果。控制台成功输出了“functional interface”
Connected to the target VM, address: '127.0.0.1:41985', transport: 'socket'
Disconnected from the target VM, address: '127.0.0.1:41985', transport: 'socket'
functional interface
Process finished with exit code 0