泛型擦除的那些事
泛型简介
泛型咱们必定再了解不过了,java 中的集结类:ArrayList
,HashMap
…
或许是,为了避免重复的模板代码,自jvm调优工具界说模板方法:
public class Schedjson解析uleTemplate<T> {
public T doSchedule(T name){
//some code
return name;
}
}
在运用的时分,直接在尖括号内< >
传入类型gitee参数,就能够避免许多烦人的强制类型转gitlab化。
ScheduleTemplate<String> scheduleTemplate = new ScheduleTemplate<>();
String name = scheduleTemplate.doSchedulgiti轮胎e("aaa");
本文的要点在于泛型擦除,泛型的运用不再过多介绍。
泛型擦除
证明存在泛型擦除
仍是运用上面的 ScheduleTemgit教程plate
类,这次咱们运用虚拟机linux javap
看一下。
9: ldc #4 // String aaa
11: invokevirtual #5 // Method git/frank/generics/ScheduleTemplajvm垃圾收回机制te.doSchedule:(Ljava/javaeelang/Object;)Ljava/lang/Object;
14: checkcast #6 // class javajvm内存结构/lang/Stringjvm参数
17: astore_2
看json文件是干什么的的出来,在从源文件解释为class文件时,现已把泛型信息去掉了,取而代之的是强制类型转化 check虚拟机linuxcast
。
再或许,咱们能够经过运行时java怎样读来看:
SchegitlabduleTemplate<String> strTemplate = new ScheduleTemplate<>虚拟机;();
ScheduleTemplate<Integer> intTemplate = new ScheduleTemplate<&jsonp跨域原理gt;();
System.out.pri虚拟机安装教程ntln(strTemplate.getClass() == intTemplate.gjvm参数etCljava面试题ass());
java 为什么要泛型擦除
咱们先来看一下 java 中方针的布局:
假定没有泛型擦除的话
假定不做泛型擦除的话,运用上面的比方,应该是下面这个姿态:
回想一下,你有多虚拟机安装教程依靠 java 供应的集结类型。
要不是有泛型擦除机制,方法区中将会充斥着各种集结对应的类型数据,例如:ArrayListgiti轮胎<String>
,ArrayList&json是什么意思lt;Integer>
,ArrayList<XXX>
,HashMap<String,XXX>
,这样的话,办虚拟机对电脑伤害大吗法区会被许多的几乎无用的类型信息填满。
怎样”避免”json文件是干什么的泛型擦除
界说擦除上限
仍是开头的比方,这次我这样界说SchedugitlableTemplate
:
public class ScheduleTemplate<T extejsonnds Number> {
p虚拟机是什么意思ublic T doSchedule(T name){
//some code
return njvm内存模型ame;
}
}
泛型界说中约束了有必要是Number
类型,所以咱们的检验代码修改成这样:
ScheduleTemplate<Long> longTemplate = new ScheduleTemplate<&gJavat;();
Long a = longTemplate.doSchedule(1L);
运用 javap 再看一下,这次泛型只擦除到了 Number
,而没有一路终究虚拟机安装教程win10 Object
。
10: invokestatijava言语c #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
13: invokevirtual #5 // Method git/frank/generics/ScheduleTemplate.doSchedule:(LjavaJSON/la虚拟机下载手机版ng/Number;)Ljava/lang/Number;
16: checkcast #6 // class java/langgit指令/Long
当然在运行时也是相同能够获取到 Number
类型的。
运用承继避免“擦除”
上面咱们说过,泛型擦除的呈现是为了避免呈现过多的类信息而规划的。
假定咱们想避开泛型擦除的话,让虚拟机额外给我创立一个类信息就能够了。最简略的方法,便是运用承继。虚拟机对电脑伤害大吗
仍是运用上面的比方,这次我承继他创立了类 StrSchedulejava模拟器TemplateImpl
。
public class StrScheduleTemplateImpl extends ScheduleTemplate<Stringgithub&g虚拟机linuxt; {
@Override
public StriJSONng doSchedule(String name) {
return super.doSjson文件是干什么的chedule(name);
}java难学吗
}
现在,咱们再运用 javap
看一下。
9: ldc #4 // String aaa
11: invokevirtual #5 // Method git/franJSONk/generics/impl/StrScheduleTemplateImpl.doSchedule:(Ljavajsonp/lang/String;)Ljava/lang/String;
14: astore_2
相同github永久回家地址的,在运行时也能够获取到类型信息。
在实践运用中,大多运用匿名内部类的方法:
ScheduleTemplate scheduleTemplate = new ScheduleTempljvm原理ate<Strin虚拟机linuxg>(){};
这种运用内部类的泛型传递方法在结构中使用非常广泛jvm参数,咱们最了解的应该便是 fastJson 中的 TypeReference
吧~
总结
在 javajvm调优 中,在源代码编译为 class 文件后jvm调优面试题,泛型信息就JSON现已被抹除掉了。
尽管泛型擦除机制被许多人诟病,但泛型擦除能够大大削减在运行时 JVM 被逼保存过多的类型信息。
假定,你真的需求在运行时获取到泛型,能够经过匿名内部类的方法结构方针,使其能够将泛型保存至运行时。github