Java泛型采用类型擦除实现;类型编译时被擦除为Object,不兼容基本数据类型;类型擦除的实现方案主要考虑向后兼容;泛型类型签名信息特定场景下反射可获取;
定义
泛型是JDK 1.5的一项新特性,它的本质是参数化类型 ParameterizedType,即带有类型参数的类型。
泛型的意义
一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。
Java在引入泛型之前,表示可变对象,通常使用Object来实现,但是在进行类型强制转换时存在安全风险。有了泛型后:
- 编译期间确定类型,保证类型安全,放的是什么,取的也是什么,不用担心抛出ClassCaseException异常。
- 提升可读性,从编译阶段就显式知道泛型集合、泛型方法等处理的对象类型是什么。
- 泛型合并了同类型的处理代码,提高了代码的重用率,增加程序的通用灵活性。
泛型的表示
泛型可以定义在类、接口、方法中,分别表示泛型类、泛型接口、泛型方法。
附加的签名信息
class SuperClass<T>{}
class SubClass extends SuperClass<String>{
public List<Map<String,Integer>> getValue(){
return null;
}
}
ParameterizedType superType = (ParameterizedType)SubClass.class.getGenericSuperclass();
for(Type actualTypeArgument : superType.getActualTypeArguments()){
System.out.println(actualTypeArgument);
}
ParameterizedType methodType = (ParameterizedType)SubClass.class.getMethod("getValue").getGenericReturnType();
for(Type type : methodType.getActualTypeArguments()){
System.out.println(type);
}
混淆时要保留签名信息
-keepattributes Signature
拓展:使用泛型签名的两个实例
Gson
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints = gson.fromJson(json, collectionType);
Retrofit
interface GitHubServiceApi{
@GET("users/{login}")
Call<User> getUserCallback(@Path("login")String login);
}
拓展:Kotlin反射的实现原理
Kotlin
class HelloWorld
-keep class kotlin.Metadata {*;}