我们有以下代码:
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
答案 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,其中返回void
或Object
。
这是expression statement (jls-14.8)的示例。
如果目标类型的函数类型返回
void
,则lambda主体为语句表达式(§14.8)或与void兼容的块({{ 3}})。
...
通过评估表达式来执行表达式语句;如果表达式具有值,则该值将被丢弃。