我喜欢上她了手游
120.43MB · 2025-11-26
List<String> 和 List<Integer> 在运行时是同一个类?约束(Constraints)
成本模型(Cost Model)
最小原语(Primitives)
List<String> 编译后变成 List,插入强制类型转换。Method.invoke() 走动态分派,需安全检查 + 参数装箱。可验证结论(Check)
javap -c 反编译泛型代码,观察类型擦除与强制转换。public class GenericDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Hello");
String s = list.get(0);
System.out.println(s);
}
}
反编译(javap -c GenericDemo):
0: new #2 // class java/util/ArrayList
...
16: invokevirtual #3 // Method java/util/List.get:(I)Ljava/lang/Object;
19: checkcast #4 // class java/lang/String
说明:
checkcast 保证类型安全。List,没有 List<String>,这就是“类型擦除”。为什么这样设计?
class Parent<T> {
T get() { return null; }
}
class Child extends Parent<String> {
@Override
String get() { return "Hi"; }
}
反编译 Child:
public java.lang.String get();
public java.lang.Object get(); // 编译器生成的桥接方法
原因:保持多态,JVM 调用时仍能找到 Object 版本。
List<String> list = new ArrayList<>();
System.out.println(list.getClass()); // class java.util.ArrayList
Type API 获取泛型信息(仅限编译期注解或运行时保留的类型签名):Field f = MyClass.class.getDeclaredField("list");
Type t = f.getGenericType(); // java.lang.reflect.ParameterizedType
性能瓶颈
Method.invoke() 都要做:
setAccessible(true) 可跳过)优化手段
method.setAccessible(true)(仅在可信环境)。JMH 对比(示意)
IOException、SQLException),用于可恢复错误。RuntimeException,用于编程错误(NullPointerException、IllegalArgumentException)。OutOfMemoryError),通常不可恢复。设计原则
性能注意
new Exception("msg", null, false, false))。List<String> 和 List<Integer> 在运行时是同一个类。MethodHandle 或代码生成。javap -c 反编译泛型代码,标注 checkcast 出现位置。ParameterizedType 获取泛型信息,解释为什么运行时仍能拿到签名。Type API)。