任何人都可以解释为什么y分配线上有无类型的转换警告?请注意,x或z分配没有警告。
public class Entity<T>
{
@SuppressWarnings("unchecked")
public <TX> Entity<TX> typed( Class<TX> type )
{
return (Entity<TX>) this;
}
@SuppressWarnings("unchecked")
public static <TX> Entity<TX> typed( Entity<?> entity, Class<TX> type )
{
return (Entity<TX>) entity;
}
public static void main( final String[] args )
{
final Entity<?> a = new Entity<Integer>();
final Entity b = (Entity) a;
final Entity<Integer> x = a.typed( Integer.class );
final Entity<Integer> y = b.typed( Integer.class );
final Entity<Integer> z = typed( b, Integer.class );
}
}
答案 0 :(得分:6)
b
的类型为Entity
,这是一种原始类型。因此它的API看起来像这样:
public Entity typed(Class type)
因此,您要从Entity
转换为Entity<Integer>
。编译器丢失了type
参数与返回的实体类型之间的任何关联,因此无法进行任何检查。
换句话说,您可以使用:
final Entity<Integer> y = b.typed(String.class);
...仍然只收到相同的警告。如果您使用x
或z
尝试相同的更改,则会收到编译时错误。
编辑:正如评论中所述,您使用原始类型的事实会删除所有泛型的痕迹。
为了便于与非泛型遗留代码接口,可以使用参数化类型(第4.5节)的擦除(第4.6节)或者元素类型为的数组类型(第10.1节)的擦除作为类型。参数化类型。这种类型称为原始类型。
然后在section 4.6:
类型擦除还将构造函数或方法的签名(第8.4.2节)映射到没有参数化类型或类型变量的签名。构造函数或方法签名的擦除是一个签名,由与s相同的名称和s中给出的所有形式参数类型的擦除组成。
答案 1 :(得分:1)
来自宣言:
final Entity<?> a = new Entity<Integer>();
输入了 a
,因此也会键入方法调用a.typed( Integer.class )
。
在typed( b, Integer.class )
中它起作用,因为该方法是通用的。
但是在
final Entity b = (Entity) a;
您已使用raw-type而不是b
的泛型版本关闭了泛型(Entity
),因此调用b.typed( Integer.class )
是无类型的。所以你得到警告。
答案 2 :(得分:0)
您正在“向下转发”a,在分配给b时删除它的类型标识符。因为b现在是无类型的,所以你得到一个无类型转换警告,因为它不再知道类型。