Eri*_*erg 3 java generics casting
我对以下代码感到困惑:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class GenericsTest<T extends List> {
public void foo() {
T var = (T) new LinkedList();
}
public static void main(String[] args) {
GenericsTest<ArrayList> gt1 = new GenericsTest<ArrayList>();
gt1.foo();
System.out.println("Done");
}
}
Run Code Online (Sandbox Code Playgroud)
无论我传递给构造函数的Type参数如何,运行时类型T似乎都是java.util.List.
那么为什么编译器T在分配var时需要转换?它不应该在编译时知道LinkedList可分配给List吗?
我理解代码是假的,我理解为什么它在运行时工作,即使它看起来不应该.令我困惑的部分是为什么编译器要求我在进行赋值时键入(T)?然而,如果没有伪造的话,它可以很好地编译.
据推测,编译器理解擦除.看起来编译器应该能够在没有强制转换的情况下编译代码.
Jon*_*eet 11
LinkedList可分配给List,但可能无法分配给T.
在某些方面,您的测试代码不应该起作用 - 它只能起作用,因为编译器有效地删除了强制转换,因为它在执行时没用(由于类型擦除).它在编译时非常有用,因为它要求您(开发人员)向编译器承诺您正在执行无法检查的有效内容.碰巧,你正在做的事情是无效的,但编译器无法知道这一点,并且没有更多信息在执行时无法检查它.您可以提供以下信息:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class GenericsTest<T extends List> {
Class<T> clazz;
public GenericsTest(Class<T> clazz) {
this.clazz = clazz;
}
public void foo() {
T var = clazz.cast(new LinkedList());
}
public static void main(String[] args) {
GenericsTest<ArrayList> gt1 =
new GenericsTest<ArrayList>(ArrayList.class);
gt1.foo();
System.out.println("Done");
}
}
Run Code Online (Sandbox Code Playgroud)
现在这将失败并出现相应的异常 - 类型信息在执行时仍然可用,我们正在使用它以安全的方式执行转换.
请注意,如果使用适当的警告进行编译,编译器将告诉您原始代码实际上并未检查任何内容.
有关此主题和许多其他主题的更多信息,请查看相当全面的Java泛型常见问题解答.
海报在评论中问道,
但是,据推测,编译器知道这就是为什么需要将转换为(T).演员有没有可能失败的方式?
这个演员阵容不会失败.但是编译器警告说,这个代码设置一个定时炸弹滴答炸毁别处有ClassCastException.
在该示例中,没有理由使用泛型,因为API都不使用类型变量T.看看更真实的泛型应用.
public class GenericsTest<T extends List> {
3 public T foo() {
4 T var = (T) new LinkedList();
5 return var;
6 }
8 public static void main(String... argv) {
9 GenericsTest<ArrayList> gt1 = new GenericsTest<ArrayList>();
10 gt1.foo();
11 System.out.println("Test one okay");
12 ArrayList<?> list = gt1.foo();
13 System.out.println("Test two okay");
14 }
}
Run Code Online (Sandbox Code Playgroud)
ClassCastException在第12行抛出A ClassCastException,没有演员阵容?调用代码完全正确.无效的强制转换(bug)位于调用方法的第4行.但是这个例外是在某个时间和地点提出的.
Java泛型的目的是确保代码是类型安全的.如果所有代码都是在没有"未选中"警告的情况下编译的,那么保证ClassCastException在运行时不会引发任何代码.但是,如果您所依赖的库写得不正确,就像这个例子一样,承诺就会被破坏.
| 归档时间: |
|
| 查看次数: |
1095 次 |
| 最近记录: |