java - 什么决定了从 lambda 创建哪个功能接口(interface)?

标签 java lambda java-8 functional-interface

请考虑这个例子:

import java.util.function.Consumer;

public class Example {
    public static void main(String[] args) {
        Example example = new Example();

        example.setConsumer(test -> System.out.println("passed string is " + test)); //uses MyConsumer, why ?
        example.getConsumer().accept("Test 1");

        example.setConsumer((MyConsumer<String>)test -> System.out.println("passed string is " + test)); //uses MyConsumer
        example.getConsumer().accept("Test 2");

        example.setConsumer((Consumer<String>)test -> System.out.println("passed string is " + test)); //uses Consumer
        example.getConsumer().accept("Test 3");
    }

    private Consumer<String> consumer;

    public Consumer<String> getConsumer() {
        return consumer;
    }

    public void setConsumer(Consumer<String> consumer) {
        this.consumer = consumer;
    }

    public void setConsumer(MyConsumer<String> consumer) {
        this.consumer = consumer;
    }

    @FunctionalInterface
    public interface MyConsumer<T> extends Consumer<T> {
        @Override
        default void accept(T value) {
            System.out.println("In consumer string: " + value); //example thing to do
            receive(value);
        }

        void receive(T value);
    }
}

我感兴趣的是第一个测试。为什么使用 MyConsumer 而不是 Consumer ?如果我有更多具有相同 lambda 结构的不同可能消费者,谁有优先权怎么办?另外,我在测试 2 中执行的转换被我的 IDE 标记为 Redundant。这意味着首先将 lamdba 创建为 MyConsumer。为什么会这样?

我正在使用 IntelliJ Idea 和 Javac。

最佳答案

按照choosing the most specific method的流程进行由语言规范定义:

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

...

A functional interface type S is more specific than a functional interface type T for an expression e if T is not a subtype of S and one of the following is true (where U1 ... Uk and R1 are the parameter types and return type of the function type of the capture of S, and V1 ... Vk and R2 are the parameter types and return type of the function type of T):

  • If e is an explicitly typed lambda expression (§15.27.1), then one of the following is true:
  • R2 is void.

  • R1 <: R2.

  • R1 and R2 are functional interface types, and there is at least one result expression, and R1 is more specific than R2 for each result expression of e.

    (The result expression of a lambda expression with a block body is defined in §15.27.2; the result expression of a lambda expression with an expression body is simply the body itself.)

  • R1 is a primitive type, and R2 is a reference type, and there is at least one result expression, and each result expression of e is a standalone expression (§15.2) of a primitive type.

  • R1 is a reference type, and R2 is a primitive type, and there is at least one result expression, and each result expression of e is either a standalone expression of a reference type or a poly expression.

  • 如果 e 是精确方法引用表达式(§15.13.1),则 i) 对于所有 i (1 ≤ i ≤ k),Ui 与 Vi 相同,并且 ii) 以下之一为真:
  • R2 is void.

  • R1 <: R2.

  • R1 is a primitive type, R2 is a reference type, and the compile-time declaration for the method reference has a return type which is a primitive type.

  • R1 is a reference type, R2 is a primitive type, and the compile-time declaration for the method reference has a return type which is a reference type.

  • 如果 e 是带括号的表达式,则这些条件之一递归地应用于包含的表达式。

  • 如果 e 是条件表达式,则对于第二个和第三个操作数中的每一个,递归地应用其中一个条件。

因此,MyConsumerConsumer 更具体,因为 Consumer(规范中的 T)不是子类型,两者都有 void 的返回值。

关于java - 什么决定了从 lambda 创建哪个功能接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41981693/

相关文章:

java - 将 Page<Entity> 转换为 PageDTO<EntityDTO>

java - 使用 lambda 表达式更新嵌套列表 : Java 8

spring-mvc - 如何在 Spring @RestController 中将 Optional<T> 作为 JSON 返回?

java - 将 HashSet 的内容与 map 进行比较

Java 8 - 更新同一流代码中的两个属性

java - 意外覆盖 : The following declarations have the same JVM signature error on specific classes hierarchy

java - Android 的最佳设计实践与 Java 不同?

java - 这是局部变量还是静态变量捕获?

java - 使用JAVA在HIVE中创建表

java - 在java代码中使用特殊字符安全吗?