繁体   English   中英

从Java的子类实例调用的类的泛型方法对返回实例的类的误解

[英]Misunderstanding of class of returned instance from generic method of class called from subclass instance in Java

例:

interface S {}

interface SS extends S {}

abstract class A<T extends S> {
    T get() {…}
}

abstract class B<BT extends SS> extends A<BT> {}

当编译器可以确定返回的对象至少为SS类型时,为什么((B)someInstanceOfB).get()返回S类型的对象(我们应该将其手动转换为SS )?

为何编译器不进行隐式类强制转换以使代码更清晰? 该代码的版本为1.5+,这对于编译器而言不是秘密。 (解决了)

更新:为什么编译器不编译B类,因为它隐式具有方法BT get() { return super.get(); } BT get() { return super.get(); }

Java 1.7+是否解决了这个问题?

通过强制转换为B您正在使用原始类型

使用原始类型会从对象中删除所有通用信息 ,无论它在哪里。

这意味着对于原始类型Bget方法看起来像在返回S (因为这是类型参数T的擦除(即,运行时使用的实际类型))。

为了避免这种情况, 切勿使用原始类型 它们专用于向后兼容以及与旧代码的交互。

转换为B<? extends SS> B<? extends SS>

不会:在Java的任何将来版本中,这个问题可能永远不会“解决”,因为正确使用泛型时将不存在该问题。

关于更新:没有, B 没有一个方法BT get() 它具有方法T get() ,其中T绑定到具有下界SS的类型参数BT 但是由于使用原始类型时会丢弃所有通用类型信息,因此T 仍会退回到原始擦除S

规则很简单,基本上说“当您使用原始类型时,它的作用就好像该类根本没有泛型”。 但是,这种情况并不总是很明显。

您没有参数化B的实例。

假设您有C类实现SS

然后, new B<C>().get(); 将返回类型为C的对象。

new B().get(); 一行,您的IDE必须告诉您“ B是原始类型。对泛型B的引用应该参数化。”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM