简体   繁体   English

Java Generics:将原始类型转换为任何可再生类型不会生成未经检查的强制转换警告

[英]Java Generics : Casting a raw type to any reifiable type doesn't generate unchecked cast warning

I have the following question regarding the code below: 关于以下代码我有以下问题:

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
   }

}

a. 一个。 Clause 1 of course won't give an unchecked cast warning 第1条当然不会给出未经检查的演员警告
b. Clause 2 also did not give an unchecked cast warning 第2条也没有给出未经检查的演员警告

I noticed that a cast from a raw type (obj) to a ANY reifiable type (like GenericBridgeMethods or GenericBridgeMethods <?>) will not give a unchecked cast warning. 我注意到从原始类型(obj)到任何可再现类型(如GenericBridgeMethods或GenericBridgeMethods <?>)的强制转换不会给出未经检查的强制转换警告。 If you run this code, a runtime error will occur at clause 2. 如果运行此代码,则在第2节将发生运行时错误。

Shouldn't the compiler give a warning at clause 2 编译器不应该在第2条中发出警告

EDIT 1: 编辑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

Can anyone explain why only clause 4 has error? 任何人都可以解释为什么只有第4条有错误?

Well, first off in GenericBridgeMethods as you have defined it, T is not a reifiable type. 好吧,首先在GenericBridgeMethods中定义它, T不是可再生类型。 Reifiable means that the type will be encoded into the class and will be available at runtime. 可恢复意味着类型将被编码到类中并且将在运行时可用。 That is not true of T . T不是这样。

Clause 2 does not give a runtime warning because it is checked: There will be a runtime check that obj is type-assignable to the GenericBridgeMethods type. 第2节没有给出运行时警告,因为它检查:将有一个运行时检查obj可以类型分配给GenericBridgeMethods类型。 Since you've opted for a wildcard as the type parameter, nothing about T needs to be checked. 由于您选择了通配符作为类型参数,因此不需要检查T任何内容。

If on the other hand you did something like this: 另一方面,如果你做了这样的事情:

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

that would give you an unchecked assignment warning because the fact that obj is a GenericBridgeMethods of String s cannot be checked at runtime. 会给你一个unchecked分配警告,因为事实上, objGenericBridgeMethodsString s不能在运行时进行检查。 However, the same warning would appear if you had done this: 但是,如果您这样做,则会出现相同的警告:

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

Edit 编辑

If you're confused as to why the compiler allows you to try to cast a List to a GenericBridgeMethods , the answer is because the compiler can't know the entire hierarchy of GenericBridgeMethods and its subclasses. 如果您对编译器允许您尝试将List转换为GenericBridgeMethods原因感到困惑,那么答案是因为编译器无法知道GenericBridgeMethods及其子类的整个层次结构。 There could be a subclass of GenericBridgeMethods that implements List , in which case the cast might be legitimate. GenericBridgeMethods的子类可以实现List ,在这种情况下,强制转换可能是合法的。

You will however get a compile error if you made GenericBridgeMethods a final class (and thus prevented it from having subclasses). 但是,如果您将GenericBridgeMethods作为最终类(因此阻止它具有子类),您收到编译错误。 In this case, you will get an inconvertable types error. 在这种情况下,您将收到无法解决的类型错误。

Just to show you your question has little to do with reifiable types and generics, take a look at this: 只是为了向您展示您的问题与可再生类型和泛型无关,请看一下:

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; 
}

You can explicitly cast obj to a CharSequence even though you know that it will fail at runtime. 您可以显式地将obj转换为CharSequence即使知道它将在运行时失败。 The reason is because all the compiler knows is that obj is a type of List . 原因是因为所有编译器都知道obj是一种List Since List is an interface, there could be an implementation of CharSequence that is also a List , and so the cast must be permitted. 由于List是一个接口,因此CharSequence的实现也可能是List ,因此必须允许强制转换。

Every explicit cast carries a degree of possibility that it could fail at runtime. 每个显式转换都有一定程度的可能性,它可能在运行时失败。 Otherwise, it would be a redundant cast and the compiler should allow you to omit the explicit cast. 否则,它将是一个冗余转换,编译器应该允许您省略显式转换。

Edit - Regarding your "edit #1" 编辑 - 关于你的“编辑#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

You are wondering why only "clause 4" does not compile. 你想知道为什么只有“第4条”不能编译。 I think I explained this already above and in the comments, but I'll go thsough this specific example for you step-by-step. 我想我已在上面和评论中对此进行了解释,但我将逐步为您提供这个具体示例。

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

Casting a1 to Number does not work because Number and ArrayList are both classes, not interfaces. a1Number不起作用,因为NumberArrayList都是类,而不是接口。 Because Java does not allow inheritance from multiple classes , for an object to be an instance of both Number and ArrayList , Number would have to be a subclass of ArrayList or vice versa. 因为Java不允许从多个继承,所以对象是NumberArrayList的实例, Number必须是ArrayList的子类,反之亦然。 This is known to not be true at compile time. 众所周知,这在编译时是不正确的。

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

Since Comparable is an interface, a subclass of ArrayList might be a Comparable . 由于Comparable是一个接口,因此ArrayList的子类可能是Comparable

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

Since List is an interface a subclass of Number could implement List . 由于List是一个接口, Number的子类可以实现List The compiler does not know when checking the cast that l1 holds an ArrayList . 编译器在检查l1持有ArrayList l1时不知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java泛型用法中特定原始类型/未选中的强制转换组合的名称 - Name for a specific raw type/unchecked cast combo in Java generics usage 带有Java泛型,类型参数和返回列表的未经检查的强制转换警告 - Unchecked cast warning with Java Generics, type parameter, and returned list 将未经检查的调用修复为原始类型警告Java - Fixing unchecked call to raw type warning Java 类型安全:未经检查的强制转换和泛型 - Type safety : Unchecked cast and Generics Java Generics Unchecked Cast警告:抽象类A <T extends A> - Java Generics Unchecked Cast Warning: abstract class A<T extends A> Java Generics:对一个通用超类进行子类化 - 是一个可再生类型的子类? - Java Generics: Subclassing a generic superclass - is subclass a reifiable type? 转换为泛型类型(T)会发出“未经检查的强制转换”警告 - Cast to generic type (T) gives “unchecked cast” warning java 转换泛型类型,没有未经检查的转换警告 - java cast generic type without unchecked cast warning Java:通用类型转换,如何解决此问题,以免抑制未经检查的警告 - Java: Generic type casting, how can I fix this so I don't suppress the unchecked warning Java泛型,将T []转换为原始类型 - Java generics, Casting a T[] to original type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM