当前位置: 首页 > 知识库问答 >
问题:

是什么决定从lambda创建哪个函数接口?

陶淳
2023-03-14

请考虑以下示例:

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标记为redundance。这意味着首先将lamdba创建为MyConsumer。为什么会这样?

我将IntelliJ Idea与javac一起使用。

共有1个答案

宋成天
2023-03-14

它是根据语言规范所定义的选择最具体方法的过程:

如果多个成员方法对方法调用都是可访问和适用的,则需要选择一个成员方法来为运行时方法调度提供描述符。Java编程语言使用的规则是:选择最具体的方法

...

对于表达式e,如果T不是S的子类型,并且下列条件之一为真(其中U1...Uk和R1是捕获S的函数类型的参数类型和返回类型,V1...Vk和R2是捕获T的函数类型的参数类型和返回类型),则函数接口类型S比函数接口类型T更具体:

  • 如果e是显式类型的lambda表达式(§15.27.1),则下列情况之一为真:

>

  • R2无效。

    R1<:R2.

    R1和R2是函数接口类型,至少有一个结果表达式,并且对于E的每个结果表达式,R1比R2更特异性。

    (具有块体的lambda表达式的结果表达式在§15.27.2中定义;具有表达式体的lambda表达式的结果表达式只是体本身。)

    R1是基元类型,R2是参考类型,且至少有一个结果表达式,e的每个结果表达式都是基元类型的独立表达式(§15.2)。

    R1是参考类型,R2是原语类型,且至少有一个结果表达式,e的每个结果表达式要么是参考类型的独立表达式,要么是多表达式。

    • 如果e是一个精确的方法引用表达式(§15.13.1),那么i)对于所有的i(1≤i≤k),Ui与Vi相同,并且ii)下列之一为真:

    >

  • R2无效。

    R1<:R2.

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

    因此,myconsumerconsumer更具体,因为consumer(规范中的t)不是子类型,并且两者的返回值都为void

  •  类似资料:
    • 问题内容: 对于没有计算机科学背景的人来说,计算机科学世界中的lambda是什么? 问题答案: Lambda来自Lambda微积分,是指编程中的匿名函数。 为什么这很酷?它允许您编写快速抛出的函数而无需命名它们。它还提供了写闭包的好方法。有了这种能力,您就可以做这样的事情。 Python 从Python片段中可以看到,函数加法器接受一个参数x,并返回一个匿名函数(即lambda),该函数接受另一个

    • 我想从AWS IAM获取用户详细信息,因此我创建了一个lambda函数,但响应代码502有一个错误。我的代码如下。

    • 本文向大家介绍什么是虚函数?什么是抽象函数?相关面试题,主要包含被问及什么是虚函数?什么是抽象函数?时的应答技巧和注意事项,需要的朋友参考一下 答: 虚函数:没有实现的,可由子类继承并重写的函数。Virtual CallSomeOne(); 抽象函数:规定其非虚子类必须实现的函数,必须被重写。public abstract void CallSomeOne();  

    • 输出为: 我用带有捕获对象lambda创建了一个std:function。它应该为lambda创建对象的本地副本,但它创建了两次副本(看看move constructor call-用粗体突出显示)。实际上,它会复制整个lambda对象。为什么?我怎么才能避免呢?我正在使用lambdas进行线程间事件处理,它们可能会捕获大量的日期,所以我试图找到一种方法来避免不必要的复制。因此,任务很简单--以最

    • 我试图创建一个Lambda函数和Lambda TriggeronSQS。下面是我的云形成模板- } 我尝试通过AWS控制台创建堆栈,但收到以下创建SQS策略的错误 检测到1个验证错误:“eventSourceArn”处的值“arn:aws:sqs:ap-south-1:219560220147:testlambda”未能满足约束:成员必须满足正则表达式模式:arn:(aws[a-zA-Z0-9-]

    • 主要内容:C语言中的函数和数学中的函数,库函数和自定义函数,参数,返回值从表面上看,函数在使用时必须带上括号,有必要的话还要传递参数,函数的执行结果也可以赋值给其它变量。例如,strcmp() 是一个用来比较字符串大小的函数,它的用法如下: str1 和 str2 是传递给 strcmp() 的参数,strcmp() 的处理结果赋值给了变量 result。 我们不妨设想一下,如果没有 strcmp() 函数,要想比较两个字符串的大小该怎么写呢?请看下面的代码: 比较字