1 |
|
正确答案: D
A 虚拟机中没有泛型,只有普通类和普通方法
B 所有泛型类的类型参数在编译时都会被擦除
C 创建泛型对象时请指明类型,让编译器尽早的做参数检查
D 泛型的类型擦除机制意味着不能在运行时动态获取List<T>中T的实际类型
1、创建泛型对象的时候,一定要指出类型变量T的具体类型。争取让编译器检查出错误,而不是留给JVM运行的时候抛出类不匹配的异常。 2、JVM如何理解泛型概念 —— 类型擦除。事实上,JVM并不知道泛型,所有的泛型在编译阶段就已经被处理成了普通类和方法。 处理方法很简单,我们叫做类型变量T的擦除(erased) 。 总结:泛型代码与JVM ① 虚拟机中没有泛型,只有普通类和方法。 ② 在编译阶段,所有泛型类的类型参数都会被Object或者它们的限定边界来替换。(类型擦除) ③ 在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。 无论我们如何定义一个泛型类型,相应的都会有一个原始类型被自动提供。原始类型的名字就是擦除类型参数的泛型类型的名字。
1.虚拟机中没有泛型,只有普通类和普通方法
2. 所有泛型类的类型参数在编译时都会被擦除
3. 创建泛型对象时请指明类型,让编译器尽早的做参数检查(Effective Java,第23条:请不要在新代码中使用原生态类型)
4. 不要忽略编译器的警告信息,那意味着潜在的ClassCastException等着你。
翻到一个桥方法的说明,设个存档点。https://blog.csdn.net/pacosonswjtu/article/details/50374131
// 通过反射得到T的真实类型
List<String> list =
new
ArrayList<String>();
//这里后面加不加String都是一样的,编译时会自动擦除:
Class clazz = list.getClass();
Type genType = clazz.getGenericSuperclass();
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if
(!(params[
0
]
instanceof
Class)) {
System.out.println(
"无法获得类型"
);
}
else
{
System.out.println(((Class)params[
0
]).getName());
输出结果:无法获得类型
为什么呢?
因为编译时会自动擦除类型。泛型等同于Object。这种情况是没有办法在运行时获得泛型的具体类型。
什么情况下可以获得泛型的具体类型呢?
如果一个类实现泛型接口时直接指定了泛型参数的类型,那么在这个类的内部会自动保存泛型参数的类型。所以以下方法是可以获得类型的:
1 2 3 4 |
|
}
输出结果:java.lang.String
通过创建一个指明了泛型参数类型的匿名类,保存泛型的具体类型。这样可以取得泛型的具体类型。
/* 通过反射在运行时动态获取List<t>中T的实际类型 */
public
class
GetGeneric {
public
List<String> list;
public
static
void
main(String[] args)
throws
NoSuchFieldException, SecurityException {
Type t = GetGeneric.
class
.getDeclaredField(
"list"
).getGenericType();
if
(ParameterizedType.
class
.isAssignableFrom(t.getClass())) {
for
(Type t1 : ((ParameterizedType) t).getActualTypeArguments()) {
System.out.print(t1);
}
}
}
}