为什么Java中的void不协变?

Mat*_*ace 9 java polymorphism covariance

如果我有这个界面:

public interface Foo {
    void bar();
}
Run Code Online (Sandbox Code Playgroud)

为什么我不能像这样实现呢?

public class FooImpl implements Foo {
    @Override
    public Object bar() {
         return new Object();
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎无效应该与一切协变.我错过了什么吗?

编辑:我应该更清楚我正在寻找设计理由,而不是它不会编译的技术原因.对所有事物进行空洞协变是否会产生负面影响?

NPE*_*NPE 13

void只是协变,void因为JLS这样说:

返回类型为R1的方法声明d1是返回类型 - 可替代另一个返回类型为R2的方法d2,当且仅当以下条件成立时:

  • 如果R1是,void那么R2是void.

  • 如果R1是基本类型,则R2与R1相同.

  • 如果R1是引用类型,则:

    • R1是R2的子类型,或者R1可以通过未经检查的转换(第5.1.9节)转换为R2的子类型,或者

    • R1 = | R2 |


Per*_*ror 5

协方差意味着,如果您的方法return typeSupertype object您可以sub-type Object在运行时返回的,则void不是super type of java.lang.Object(或除 MR NPE 回答的本身之外的任何对象)


bes*_*sss 2

从技术上讲void,不能是协变返回类型,因为调用者需要知道堆栈布局。调用返回对象的函数将在 INVOKEVIRTUAL/INTERFACE 之后在堆栈顶部产生一个对象引用。Void返回类型在堆栈顶部没有留下任何内容,因此这些函数是二进制不兼容的。

因此,JLS 正确地说这是不可能的。