什么决定了从 lambda 创建哪个功能接口?

What decides which functional interface to create from a lambda?

请考虑这个例子:

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)不是子类型,并且两者都有 return void.

的值