Fia*_*ary 3 java generics type-erasure
声明类型参数的类时
<T extends A & B & C>,类型擦除过程将替换T为类型A.但是,如果类型的变量T调用方法,接口声明B或C,什么是Java的关系呢?
当我们创建泛型类型的实例时ArrayList<String>,类型参数String也将被删除,但调用get方法将返回类型
String,这些信息来自何处,因为它已被删除?
我知道使用java反射,但我需要一些具体的解释.
不使用反射 - 铸造是.例如,请使用以下代码:
interface A {
void a();
}
interface B {
void b();
}
interface C {
void c();
}
class Generic<T extends A & B & C> {
T t;
Generic(T t) {
this.t = t;
}
void callMethods() {
t.a();
t.b();
t.c();
}
}
Run Code Online (Sandbox Code Playgroud)
现在看一下Generic(构造函数已删除)的字节码:
class Generic extends java.lang.Object{
A t;
void callMethods();
Code:
0: aload_0
1: getfield #2; //Field t:LA;
4: invokeinterface #3, 1; //InterfaceMethod A.a:()V
9: aload_0
10: getfield #2; //Field t:LA;
13: checkcast #4; //class B
16: invokeinterface #5, 1; //InterfaceMethod B.b:()V
21: aload_0
22: getfield #2; //Field t:LA;
25: checkcast #6; //class C
28: invokeinterface #7, 1; //InterfaceMethod C.c:()V
33: return
}
Run Code Online (Sandbox Code Playgroud)
checkcast在每次invokeinterface调用b()和之前请注意说明c().
结果就好像Generic实际上是这样编写的:
class Generic<T extends A> {
T t;
Generic(T t) {
this.t = t;
}
void callMethods() {
t.a();
((B) t).b();
((C) t).c();
}
}
Run Code Online (Sandbox Code Playgroud)
至于你的问题ArrayList- 关于get()作为列表元素类型的返回类型的信息仍然存储为ArrayList类的一部分.编译器将再次在调用代码中插入强制转换,因此:
ArrayList<String> strings = new ArrayList<String>();
strings.add("foo");
String x = strings.get(0);
Run Code Online (Sandbox Code Playgroud)
在执行时相当于:
ArrayList strings = new ArrayList();
strings.add("foo");
String x = (String) strings.get(0);
Run Code Online (Sandbox Code Playgroud)
这样做的一个重要方面是,您无法在执行时询问ArrayList对象是什么T- 该信息已被删除.
| 归档时间: |
|
| 查看次数: |
403 次 |
| 最近记录: |