关于以下代码我有以下问题:
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
}
}
Run Code Online (Sandbox Code Playgroud)
一个.第1条当然不会给出未经检查的投射警告
b.第2条也没有给出未经检查的演员警告
我注意到从原始类型(obj)到ANY可再现类型(如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
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释为什么只有第4条有错误?
Mar*_*ers 11
好吧,首先GenericBridgeMethods,你已经定义它,T不是一个可再生的类型.可恢复意味着该类型将被编码到类中,并将在运行时可用.事实并非如此T.
第2条没有给出运行时警告,因为它被检查:将有一个obj类型可分配给GenericBridgeMethods类型的运行时检查.由于您选择了通配符作为类型参数,因此无需T检查任何内容.
另一方面,如果你做了这样的事情:
GenericBridgeMethods<String> g1 = (GenericBridgeMethods<String>) obj;
Run Code Online (Sandbox Code Playgroud)
这将让你一个unchecked分配警告,因为事实obj是GenericBridgeMethods的Strings不能在运行时进行检查.但是,如果您这样做,则会出现相同的警告:
List<String l1 = (List<String>) obj;
Run Code Online (Sandbox Code Playgroud)
如果您对编译器为什么允许您尝试将a转换List为a 感到困惑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;
}
Run Code Online (Sandbox Code Playgroud)
即使你知道它会在运行时失败,你也可以明确地转换obj为a .原因是因为所有编译器都知道这是一种类型.由于是一个接口,有可能是的实现,这也是一个,所以演员必须被允许.CharSequenceobjListListCharSequenceList
每个显式转换都有一定程度的可能性,它可能在运行时失败.否则,它将是一个冗余转换,编译器应该允许您省略显式转换.
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
Run Code Online (Sandbox Code Playgroud)
你想知道为什么只有"第4条"不能编译.我想我已在上面和评论中对此进行了解释,但我将逐步为您提供这个具体示例.
ArrayList a1 = new ArrayList<Integer>(); // clause 3
Number n1 = (Number)a1; // clause 4 ERROR
Run Code Online (Sandbox Code Playgroud)
铸造a1到Number不工作,因为Number和ArrayList都是类,而不是接口.由于Java不允许继承多个类,一个对象既实例Number和ArrayList,Number将必须的一个子类ArrayList,反之亦然.众所周知,这在编译时是不正确的.
ArrayList a1 = new ArrayList<Integer>(); // clause 3
Comparable c1 = (Comparable)a1; // clause 5
Run Code Online (Sandbox Code Playgroud)
由于Comparable是一个接口,一个子类ArrayList可能是一个Comparable.
List l1 = new ArrayList<Integer>(); // clause 6
Number n2 = (Number)l1; // clause 7
Run Code Online (Sandbox Code Playgroud)
因为List接口是一个Number可以实现的子类List.编译器在检查l1持有的转换时不知道ArrayList.
| 归档时间: |
|
| 查看次数: |
2111 次 |
| 最近记录: |