考虑以下两个类:
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字节码)中实现这一点:
答案 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()
可能会返回int
或Integer
,具体取决于变量的静态类型,这会非常混乱。
答案 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)
原语的问题是它们在堆栈上需要不同的空间量...而不是在堆栈上占用相同空间量的对象引用。并且你不能拥有一个可变大小的堆栈框架,因为否则在运行时堆栈将不知道返回到方法退出的位置