参考:
泛型的作用:
解决类型的转换问题,避免转换错误(CastException)、类型自动推断;
原生态是什么意思?
不定义<> 表示原生态类型(获取class对象时,需要用原生态类型,因为编译时被擦除);
1. Java泛型是如何工作的,什么是泛型擦除?
Java泛型是通过类型擦除实现的,编译时会擦除泛型相关的信息,运行时不存在泛型的信息,比如:
List<Integer> 在运行时,其实是 List;
为什么要这么做呢?这是因为兼容jdk1.5以前的版本,不得不说Java用心良苦;
泛型擦除也就是在编译成字节码之前先对类型进行检查,然后再擦除(所有类型参数都用限定的类型替换,包括类、变量、方法)如果调用泛型返回,擦除时,插入强制类型转换;
2.Java 泛型类、泛型接口、泛型方法有和区别?
- 泛型类是在实例化时才能确定的类型,也就是实例化时,必须明确指定具体类型;(class Test<T>{},实例化时,必须指定T的类型);
- 接口与泛型类一致;
- 泛型方法所在的类可是泛型类,也可不是,如非必要,尽可能使用泛型方法;
static <T> void method2(List<T> list) {
for (T t : list) {
}
}
Java 的泛型机制虽然在编译期间进行了擦除,但是在编译 Java 源代码成 class 文件中还是保存了泛型相关的信息,这些信息被保存在 class 字节码的常量池中,使用了泛型的代码处会生成一个 signature 签名字段,通过签名 signature 字段指明这个常量池的地址,JDK 提供了方法去读取这些泛型信息的方法,然后再借助反射就可以获得泛型参数的具体类型:
如下例子:
class MyTest {
static void main(String[] bb) {
// 获取父泛型
ParameterizedType type = (ParameterizedType) Bar.class.getGenericSuperclass();
System.out.println(type.getActualTypeArguments()) // [class java.lang.String]
// 获取成员域的泛型
ParameterizedType type2 = Foo.class.getDeclaredField("children").getGenericType();
System.out.println(type2.getActualTypeArguments()) // [class MyTest$Bar]
// 获取 方法参数 的泛型
ParameterizedType paramType = (ParameterizedType) Foo.class.getMethod("foo", List.class).getGenericParameterTypes()[0];
System.out.println(paramType.getActualTypeArguments()[0]) // class java.lang.String
// 获取类的泛型
System.out.println(Foo.class.getTypeParameters()[0].getBounds()[0]) // interface java.lang.CharSequence
}
static class Foo<T extends CharSequence> {
public List<Bar> children = new ArrayList<Bar>();
List<StringBuilder> foo(List<String> foo) { return null; }
void bar(List<? extends String> param) {
}
}
static class Bar extends Foo<String> {}
}
网友评论