Java 意外的未检查转换警告

Java 意外的未检查转换警告,java,generics,Java,Generics,有人能解释为什么y分配行上有非类型转换警告吗?请注意,在x或z指定上都没有警告 public class Entity<T> { @SuppressWarnings("unchecked") public <TX> Entity<TX> typed( Class<TX> type ) { return (Entity<TX>) this; } @SuppressWarnings(

有人能解释为什么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 );
    }
}
公共类实体
{
@抑制警告(“未选中”)
公共实体类型(类类型)
{
返回(实体)本文件;
}
@抑制警告(“未选中”)
公共静态实体类型(实体、类类型)
{
返回(实体)实体;
}
公共静态void main(最终字符串[]args)
{
最终实体a=新实体();
最终实体b=(实体)a;
最终实体x=a.typed(Integer.class);
最终实体y=b.typed(Integer.class);
最终实体z=类型化(b,Integer.class);
}
}

b
属于原始类型的
实体
。因此,其API如下所示:

public Entity typed(Class type)
因此,您正在从
实体
转换为
实体
。编译器已丢失
类型
参数与返回的实体类型之间的任何关联,因此无法执行任何检查

换言之,您可以使用:

final Entity<Integer> y = b.typed(String.class);
最终实体y=b.typed(String.class);
。。。但仍然只收到相同的警告。如果您尝试对
x
z
进行相同的更改,则会出现编译时错误

编辑:如注释中所述,使用原始类型会删除所有泛型的痕迹

发件人:

为了便于与非通用遗留代码接口,可以使用参数化类型(§4.5)的擦除(§4.6)或元素类型为参数化类型的数组类型(§10.1)的擦除作为类型。这种类型称为原始类型

然后在:

类型擦除还将构造函数或方法的签名(§8.4.2)映射到没有参数化类型或类型变量的签名。构造函数或方法签名s的擦除是一个签名,由与s相同的名称和s中给出的所有形式参数类型的擦除组成

您正在“向下转换”a,在分配给b时删除它的类型标识符。由于b现在是非类型化的,您将收到非类型化转换警告,因为它不再知道类型。

来自声明:

final Entity<?> a = new Entity<Integer>();

您已经关闭了泛型(对于
b
,使用原始类型而不是
实体的泛型版本),因此调用
b.typed(Integer.class)
是非类型化的。因此,您得到了警告。

您的实体
b
,在从
a
进行强制转换后是非类型化的,因此当您使用
b.typed(Integer.class)
将其转换回时,它是非类型化的。泛型类型与类类型不同;“向下浇铸”时不会保留它们。请注意,“类型化”方法本身是参数化的。有两个类型参数。@KonstantinKomissarchik:这无关紧要-当您对原始类型调用方法时,这一切都会消失。只是编译器没有说我在对原始类型调用方法。这意味着我正在从一个实体到另一个实体的赋值中进行未经检查的转换。如果由TX完全指定,则类型。@KonstantinKomissarchik:但调用中不存在
TX
,因为您是在原始类型上调用它。恰巧,在代码中使用Java 7中的
javac
也会发出警告,表明您正在对原始类型调用方法:“Test.Java:21:warning:[unchecked]未选中调用
typed(Class)
(以及更多详细信息),作为原始类型
实体的成员。谢谢。第4.6节中的引用就是我想要的解释。
final Entity b = (Entity) a;