不使用反射 - 使用强制转换。比如下面这段代码:
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();
}
}
现在查看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
}
注意invokeinterface 对b() 和c() 的每个调用之前的checkcast 指令。
结果就好像Generic实际上是这样写的:
class Generic<T extends A> {
T t;
Generic(T t) {
this.t = t;
}
void callMethods() {
t.a();
((B) t).b();
((C) t).c();
}
}
至于您关于ArrayList 的问题-关于get() 作为列表元素类型的返回类型的信息仍存储为ArrayList 类的一部分。编译器将再次在调用代码中插入强制转换,所以:
ArrayList<String> strings = new ArrayList<String>();
strings.add("foo");
String x = strings.get(0);
在执行时等同于:
ArrayList strings = new ArrayList();
strings.add("foo");
String x = (String) strings.get(0);
其中一个重要方面是,您不能在执行时询问ArrayList 对象T 是什么 - 该信息已被删除。