主页 什么是函数式接口?
文章
取消

什么是函数式接口?

你好,我是猿java。

Lambda官方说明

上一篇文章我们分析了lambda是什么,里面提到一个点:lambda必须依赖于函数式接口,这篇博文我们就来一起分析下什么是函数式接口

首选我们看一个List遍历的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class ListTest {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);

        //for method
        for(int i = 0; i < list.size(); i++){
            System.out.println("i=" + i);
        }
        // lambda method
        list.forEach(System.out::println);
    }

    // forEach method
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
}

/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

从上面的代码可以看出,从jdk8开始,list增加了forEach()方法进行遍历,forEach()接收一个Consumer类型的参数,进入Consumer可以看出该类有一个@FunctionalInterface 的注解,这个标识Consumer是一个函数式接口,接下来我们进入FunctionalInterface这个注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
 * 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
 * @jls 9.6.4.9 @FunctionalInterface
 * @since 1.8
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

从源码中我们可以抽取FunctionalInterface注解的几个重要信息:

  • FunctionalInterface注解是从jdk1.8 开始引入
  • FunctionalInterface注解是一种信息性注释类型,用于指示接口类型声明旨在成为 Java 语言规范定义的功能接口
  • 函数式接口有且仅有一个抽象方法,因为所有的类默认继承java.lang.Object类,所以从Object类继承下来的抽象方法不会计入该接口的抽象方法总数
  • 函数式接口的实例有3种创建方式:lambda表达式、方法引用或构造函数引用
  • FunctionalInterface注解只能用于接口类型,而不能用于注释类型、枚举或类,如果此注解用于非接口,则编译器会生成错误信息
  • 只要接口符合函数式接口的特征,不论接口是否加了FunctionalInterface注解,编译器都会把这个接口当做函数式接口处理

鸣谢

如果你觉得本文章对你有帮助,感谢转发给更多的好友,关注我:猿java,为你呈现更多的硬核文章。

drawing

lambda表达式是什么?

Lua script attempted to access a non local key in a cluster node