对象进行泛型类型转换的未经检查警告的定义在哪里?

问题描述 投票:0回答:2

JLS 5.1.9定义未经检查的转换如下:

设G用n类参数命名泛型类型声明。

从原始类或接口类型G到G<T1,...,Tn>形式的任何参数化类型都有未经检查的转换。

从原始数组类型G[]G<T1,...,Tn>[]形式的任何数组类型类型都有未经检查的转换。

使用未经检查的转换会导致编译时未经检查的警告,除非G<...>是参数化类型,其中所有类型参数都是无界通配符,或者SuppressWarnings注释禁止未经检查的警告

据我所知,如果您将原始类型转换为具有有界类型参数的泛型类型,则会发生未经检查的转换。那么为什么下面的代码生成一个未经检查的警告:

public class DoubleStar{

    public static void print(Object object){
       ((A<String>)object).print();
    }

    public static void main(String[] args){
        print(new Object());
    }
}

class A<T>{
    public void print(){
        System.out.print("HELLO");
    }
}

由于Object不是原始类型(AFAIK),为什么上面的代码会生成未经检查的强制转换警告以及定义此行为的位置?

java generics type-conversion warnings javac
2个回答
1
投票

您正在查看错误的部分,这就是为什么它在您的示例的上下文中似乎没有意义。

您的警告是未经检查的演员表。您正在查看有关未经检查的转换的部分(related)。

See 5.5.2 "Checked Casts and Unchecked Casts"

当且仅当S <:T(§4.10)时,静态地知道从类型S到类型T的转换是正确的。

除非至少满足下列条件之一,否则不会检查从类型S到参数化类型(第4.5节)T的强制转换:

  • S <:T
  • T的所有类型参数(第4.5.1节)都是无界通配符
  • T <:S和S没有T以外的子类型X,其中X的类型参数不包含在T的类型参数中。

除非S <:T,否则不会检查从类型S到类型变量T的强制转换。

如果从| S |转换,则从S到T的未经检查的强制转换完全取消选中到| T |静态地知道是正确的。否则,它部分未经检查。

除非被SuppressWarnings注释(第9.6.3.5节)抑制,否则未经检查的强制转换会导致编译时未经检查的警告。

如果静态不知道是否正确并且未取消选中,则检查强制转换。

如果对引用类型的强制转换不是编译时错误,则有几种情况:

  • 演员静态地知道是正确的。

没有对这样的演员表执行运行时动作。

  • 演员阵容完全不受限制。

没有对这样的演员表执行运行时动作。

  • 演员是部分未经检查的演员。

这样的演员需要运行时有效性检查。执行检查就像是在| S |之间进行了检验和| T |,如下所述。

  • 演员是经过检验的演员。

这样的演员需要运行时有效性检查。如果运行时的值为null,则允许转换。否则,令R为运行时引用值引用的对象的类,并且让T为转换运算符中指定的类型的擦除(第4.6节)。强制转换必须在运行时通过§5.5.3中的算法检查类R是否与类型T兼容。

注意,当这些规则首次应用于任何给定的强制转换时,R不能是接口,但如果规则是递归应用的,则R可以是接口,因为运行时引用值可以引用其元素类型是接口类型的数组。


0
投票

因为当你将Object投射到A<String>时,编译器无法检查(或生成要检查的代码)Object确实是A<String>而不是A<Integer>(或其他)。

© www.soinside.com 2019 - 2024. All rights reserved.