gpt4 book ai didi

Java 泛型 : Casting a raw type to any reifiable type doesn't generate unchecked cast warning

转载 作者:搜寻专家 更新时间:2023-10-31 08:29:00 25 4
gpt4 key购买 nike

我对下面的代码有以下疑问:

public class GenericBridgeMethods <T> {

public static void main(String[] args) {
List obj = new ArrayList<Integer>();
List <?> l1 = (List<?>) obj; // clause 1
GenericBridgeMethods <?> g1 = (GenericBridgeMethods<?>) obj; // clause 2
}

}

一个。第 1 条当然不会给出 unchecked cast warning
b.第2条也没有给出unchecked cast warning

我注意到从原始类型 (obj) 到任何可具体化类型(如 GenericBridgeMethods 或 GenericBridgeMethods )的转换不会给出未经检查的转换警告。如果运行此代码,将在第 2 条出现运行时错误。

编译器是否应该在第 2 条给出警告

编辑 1:

    ArrayList a1 = new ArrayList<Integer>(); // clause 3
Number n1 = (Number)a1; // clause 4 ERROR
Comparable c1 = (Comparable)a1; // clause 5

List l1 = new ArrayList<Integer>(); // clause 6
Number n2 = (Number)l1; // clause 7
Comparable c2 = (Comparable)l1; // clause 8

谁能解释一下为什么只有第4条有错误?

最佳答案

好吧,首先在 GenericBridgeMethods 中定义了它,T 不是可具体化的类型。 Reifiable 意味着该类型将被编码到类中并在运行时可用。 T 不是这样。

第 2 条不会给出运行时警告,因为它已被检查:将进行运行时检查以确保 obj 类型可分配给 GenericBridgeMethods类型。由于您已选择通配符作为类型参数,因此无需检查有关 T 的任何内容。

如果另一方面你做了这样的事情:

GenericBridgeMethods<String> g1 = (GenericBridgeMethods<String>) obj;

给你一个未经检查的赋值警告,因为 objStringGenericBridgeMethods无法在运行时检查。但是,如果您这样做,则会出现相同的警告:

List<String l1 = (List<String>) obj;

编辑

如果您对为什么编译器允许您尝试将 List 转换为 GenericBridgeMethods 感到困惑,答案是因为编译器无法知道GenericBridgeMethods 及其子类的整个层次结构。可能有一个 GenericBridgeMethods 的子类实现了 List,在这种情况下,转换可能是合法的。

但是,如果您将 GenericBridgeMethods 设为最终类(并因此阻止它拥有子类),您得到一个编译错误。在这种情况下,您将收到不可转换的类型错误。

只是为了向您展示您的问题与可具体化的类型和泛型无关,请看一下:

public static void main(String[] args) {
List obj = new ArrayList<Integer>();

//this is allowed (no warning), even though it will fail at runtime
CharSequence sequence = (CharSequence) obj;
}

您可以显式地将 obj 转换为 CharSequence,即使知道它会在运行时失败。原因是因为编译器只知道 objList 的一种。由于 List 是一个接口(interface),因此 CharSequence 的实现可能也是一个 List,因此必须允许转换。

每个 显式转换都有一定程度的在运行时失败的可能性。否则,这将是一个冗余转换,编译器应该允许您省略显式转换。

编辑 - 关于您的“编辑 #1”

ArrayList a1 = new ArrayList<Integer>(); // clause 3
Number n1 = (Number)a1; // clause 4 ERROR
Comparable c1 = (Comparable)a1; // clause 5

List l1 = new ArrayList<Integer>(); // clause 6
Number n2 = (Number)l1; // clause 7
Comparable c2 = (Comparable)l1; // clause 8

您想知道为什么只有“第 4 条”不能编译。我想我已经在上面和评论中对此进行了解释,但我将逐步为您完成这个具体示例。

ArrayList a1 = new ArrayList<Integer>(); // clause 3
Number n1 = (Number)a1; // clause 4 ERROR

a1 转换为 Number 不起作用,因为 NumberArrayList 都是类,而不是接口(interface)。因为 Java 不允许从多个 继承,对于一个对象同时是NumberArrayList 的实例,Number 必须是 ArrayList 的子类,反之亦然。这在编译时是不正确的。

ArrayList a1 = new ArrayList<Integer>(); // clause 3
Comparable c1 = (Comparable)a1; // clause 5

由于 Comparable 是一个接口(interface),ArrayList 的子类可能是一个 Comparable

List l1 = new ArrayList<Integer>(); // clause 6
Number n2 = (Number)l1; // clause 7

由于 List 是一个接口(interface),Number 的子类可以实现 List。编译器在检查 l1 包含 ArrayList 的转换时并不知道。

关于Java 泛型 : Casting a raw type to any reifiable type doesn't generate unchecked cast warning,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7676981/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com