首页 > 解决方案 > Object 到泛型类型转换的未检查警告的定义在哪里?

问题描述

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),为什么上面的代码应该生成未经检查的强制转换警告以及定义此行为的位置?

标签: javagenericstype-conversionwarningsjavac

解决方案


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

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

请参阅 5.5.2 “检查型演员表和未检查型演员表”

当且仅当 S <: T (第 4.10 节)时,从类型 S 到类型 T 的强制转换静态地被认为是正确的。

从类型 S 到参数化类型(第 4.5 节)的强制转换是未经检查的,除非至少满足以下条件之一:

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

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

如果从 |S| 的转换,则从 S 到 T 的未经检查的转换是完全未经检查的。到 |T| 静态已知是正确的。否则,它是 部分 unchecked

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

如果不是静态地知道它是正确的并且它不是未经检查的,则检查强制转换

如果转换为引用类型不是编译时错误,则有以下几种情况:

  • 演员阵容静态已知是正确的。

不会对此类强制转换执行任何运行时操作。

  • 演员表是完全未经检查的演员表。

不会对此类强制转换执行任何运行时操作。

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

这样的强制转换需要运行时有效性检查。执行检查就好像该强制转换是 |S| 之间的检查强制转换。和 |T|,如下所述。

  • 演员表是检查演员表。

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

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


推荐阅读