为什么带有void return-type方法的功能接口接受任何return-type方法?

时间:2019-09-27 11:09:09

标签: java void functional-interface

我们有以下代码:

public class Test {
    public static Object foo() {
        System.out.println("Foo");
        return new Object();
    }

    public static void main(String[] args) {
        J j = Test::foo;
        j.m();
    }

}
interface J {
    void m();
}

此代码将起作用。关键线是

J j = Test::foo;

尽管interface J声明它具有void函数,但Test::foo返回了Object

尽管实现接口时不能覆盖方法(这很明显)。 仅当接口的方法为void时此方法才有效,否则将不会编译代码。有人可以告诉我为什么这样做会起作用吗? :D

2 个答案:

答案 0 :(得分:2)

我不确定到底是什么使您感到困惑,所以这是您查看示例的其他方式。


J j = Test::foo;

可以改写为

J j = () -> Test.foo();

因为它从m()功能接口为J方法提供了主体,并且该方法不需要任何参数(这就是为什么以() ->开头的原因)。

但这可以看作是

的缩写
J j = new J(){
    public void m(){
        Test.foo(); //correct despite `foo` returning value    
    }
};

这是正确的,因为Java允许我们忽略被调用方法的返回值,就像List#add(E element)返回boolean值的情况一样,但是仍然可以编写类似list.add(1)的代码无需处理返回值。

答案 1 :(得分:2)

  

尽管interface J声明它具有void函数,但Test::foo返回了Object

Test::foo返回的内容是不准确的。在不同的情况下,它可能意味着不同的事情。

Supplier<Object>  a = Test::foo;
J                 b = Test::foo;
Runnable          c = Test::foo;

更准确地说Test::foo可以代表a target type the functional method,其中返回voidObject

这是expression statement (jls-14.8)的示例。

  

如果目标类型的函数类型返回void,则lambda主体为语句表达式§14.8)或与void兼容的块({{ 3}})。
  ...
  通过评估表达式来执行表达式语句;如果表达式具有值,则该值将被丢弃。