Java泛型:将原始类型强制转换为任何可重新定义的类型不会';不生成未检查的强制类型转换警告
关于以下代码,我有以下问题:Java泛型:将原始类型强制转换为任何可重新定义的类型不会';不生成未检查的强制类型转换警告,java,generics,Java,Generics,关于以下代码,我有以下问题: public class GenericBridgeMethods <T> { public static void main(String[] args) { List obj = new ArrayList<Integer>(); List <?> l1 = (List<?>) obj; // clause 1 GenericBridgeMethods &l
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
}
}
公共类GenericBridgeMethods{
公共静态void main(字符串[]args){
List obj=new ArrayList();
List l1=(List)obj;//第1条
GenericBridgeMethods g1=(GenericBridgeMethods)obj;//子句2
}
}
a。第1条当然不会给出未经检查的演员阵容警告B第2条也没有给出未经检查的演员阵容警告 我注意到,从原始类型(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
ArrayList a1=新建ArrayList();//第3条
编号n1=(编号)a1;//第4条错误
可比c1=(可比)a1;//第5条
列表l1=新的ArrayList();//第6条
编号n2=(编号)l1;//第7条
可比c2=(可比)l1;//第8条
有人能解释为什么只有第4条有错误吗?首先,在您定义的
GenericBridgeMethods
中,T
不是可修改的类型。Reifiable意味着该类型将被编码到类中,并在运行时可用。对于T
,情况并非如此
第2条没有给出运行时警告,因为它已被选中:将进行运行时检查,确保obj
的类型可分配给GenericBridgeMethods
类型。由于您选择了通配符作为类型参数,因此无需检查T
另一方面,如果你做了这样的事情:
GenericBridgeMethods<String> g1 = (GenericBridgeMethods<String>) obj;
编辑
如果您不明白为什么编译器允许您尝试将列表
强制转换为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;
}
你想知道为什么只有“第4条”没有编译。我想我已经在上面和评论中解释了这一点,但我会一步一步地为您介绍这个具体的例子
ArrayList a1 = new ArrayList<Integer>(); // clause 3
Number n1 = (Number)a1; // clause 4 ERROR
由于Comparable
是一个接口,ArrayList
的子类可能是Comparable
List l1 = new ArrayList<Integer>(); // clause 6
Number n2 = (Number)l1; // clause 7
List l1=new ArrayList();//第6条
编号n2=(编号)l1;//第7条
由于
List
是一个接口,Number
的子类可以实现List
。编译器在检查转换时不知道l1
持有ArrayList
子句1和2处的转换是否转换为可修改类型。这就是我的意思。第2条确实给出了一个运行时错误!这是错误-java.lang.ClassCastException:java.util.ArrayList不能强制转换为GenericBridgeMethod。@yapkm01:java库中没有运行时警告。它当然会失败,因为ArrayList不是GenericBridgeMethod。但是编译器无法知道,因为可能存在实现List
的GenericBridgeMethod
的子类。很抱歉,我将其更改为error。对它给出了一个运行时错误。如果是这种情况,编译器应该给出一个未检查的强制转换warning@yap:未选中的强制类型转换与泛型有关。你的问题真的与泛型无关;他们在掩盖这个问题。这根本不是关于可偿还性。未选中的警告意味着强制转换不会在运行时实际检查类型;在这里你不会明白这一点,因为很明显,类型确实在运行时被检查过(否则你不会得到ClassCastException
!!)。我在回答中说了这一点,但我要重申:unchecked并不意味着“在编译时未检查”,它意味着“在运行时未检查”。
ArrayList a1 = new ArrayList<Integer>(); // clause 3
Number n1 = (Number)a1; // clause 4 ERROR
ArrayList a1 = new ArrayList<Integer>(); // clause 3
Comparable c1 = (Comparable)a1; // clause 5
List l1 = new ArrayList<Integer>(); // clause 6
Number n2 = (Number)l1; // clause 7