请考虑以下两类:

public interface Foo<T>
{
    public T moo();
}

public class IntFoo implements Foo<Integer>
{
    public int moo()
    {
        return 0;
    }
}

此代码将在public int moo处产生错误,表示int与重写的方法的返回类型Integer不兼容。严格来说,这是正确的,因为int不直接等于Integer。但是,我们都知道可以使用自动装箱将它们隐式地彼此转换。鲜为人知的是,在此示例中,编译器会生成一个桥接方法:
public class IntFoo implements Foo<Integer>
{
    public <synthetic> <bridge> Object moo()
    {
        return this.moo(); // upcast
    }

    public Integer moo() {
        return 0;
    }
}

之所以必须这样做,是因为JVM在解析方法时会区分返回类型,并且由于Foo.moo的擦除返回类型为Object,因此编译器生成了一个桥方法,该桥方法具有与该方法相同的签名。

我想知道为什么这也不适用于原始多态返回类型:
public class IntFoo implements Foo<Integer>
{
    public <synthetic> <bridge> Object moo()
    {
        return Integer.valueOf(this.moo());
    }

    public int moo()
    {
        return 0;
    }
}

似乎没有任何理由不具有此功能:
IntFoo intFoo = new IntFoo();
Foo<Integer> foo = intFoo;
Integer i = foo.moo(); // calls the synthetic method, which boxes the result of the actual implementation

实际上,REPL session 的屏幕截图显示,我什至可以在o​​jit_a(编译为Java字节码)中实现此功能:

custom programming language

最佳答案

与这些问题一样,答案是您必须问语言设计师。我看不到无法完成此操作的任何原因。但是我认为此功能将毫无意义。正如您在问题中指出的那样,只有在静态类型为moo的变量上调用IntFoo时,才会返回原语。在类型为Foo<Integer>的变量上,无论如何都会返回Integer。因此,您可以通过执行此操作来实现基本相同的目的。

public class IntFoo implements Foo<Integer> {

    @Override
    public Integer moo() { return mooAsInt(); }

    public int mooAsInt() { return 0; }
}

我个人认为这样做比较好,因为装箱/不装箱会更明显。在您的建议中,moo()可能会返回intInteger,具体取决于变量的静态类型,这将非常令人困惑。

关于java - 为什么不能将原始类型与多态返回类型一起使用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32418456/

10-12 00:32
查看更多