为什么不能使用具有多态返回类型的原始类型?

时间:2015-09-05 22:59:01

标签: java polymorphism primitive return-type

考虑以下两个类:

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

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

此代码将在public int moo处产生错误,称int与重写方法的返回类型{{不兼容1}}。严格来说,这是事实,因为Integer <{1}}。但是,我们都知道可以使用auto(un)boxing将它们隐式转换为彼此。更不知道的是编译器在此示例中生成桥接方法:

int

必须这样做是因为JVM在解析方法时区分返回类型,并且因为Integer的擦除返回类型是public class IntFoo implements Foo<Integer> { public <synthetic> <bridge> Object moo() { return this.moo(); // upcast } public Integer moo() { return 0; } } ,编译器生成的桥接方法具有与方法

我想知道为什么这对原始多态返回类型也不起作用:

Foo.moo

似乎没有任何理由不具备此功能:

Object

事实上,REPL会话的这个屏幕截图显示我甚至能够在我的custom programming language(编译为Java字节码)中实现这一点:

REPL session

3 个答案:

答案 0 :(得分:6)

与这些问题一样,答案是您必须向语言设计师询问。我无法理解为什么无法做到这一点。但是在我看来这个功能毫无意义。正如你在问题中指出的那样,只有在静态类型moo的变量上调用IntFoo时才会返回原语;对于Foo<Integer>类型的变量,无论如何都会返回Integer。所以你可以通过这样做来实现基本相同的东西。

public class IntFoo implements Foo<Integer> {

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

    public int mooAsInt() { return 0; }
}

就我个人而言,我认为这更好,因为当拳击没有发生时,它会更加明显。在您的提案中,moo()可能会返回intInteger,具体取决于变量的静态类型,这会非常混乱。

答案 1 :(得分:3)

在我的拙见中,原因纯粹是语法上的。正如您在问题中所演示的那样,可以生成返回int的方法和实现Foo接口方法的方法,该方法在字节码中返回Object

但是,如果从Java语法的角度来看问题(即不是字节码),

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

应该覆盖它没有的方法Integer moo()。正如您自己所说,Java区分了返回类型,int moo()Integer moo()不同。

答案 2 :(得分:2)

原语的问题是它们在堆栈上需要不同的空间量...而不是在堆栈上占用相同空间量的对象引用。并且你不能拥有一个可变大小的堆栈框架,因为否则在运行时堆栈将不知道返回到方法退出的位置