泛型擦除
一句话总结:泛型只在编译期生效!运行期不起作用!
先介绍问题,再引申到理论,比死记理论要好。最近要封装一个通用DAO类,理所当然想到使用泛型,这样不同业务Service调用此DAO类就不用再转换Entity类:
public class CommonDao<T> { private EntityManager entityManager; public T findById(String id) { // 重点:这里T.class会报错,这里是问题 return (T) this.entityManager.find(T.class, id); } } // Service示例,CommonDao传入具体类型,方法无需类型转换 public class CatService { private CommonDao<CatEntity> commonDao; } public class DogService { private CommonDao<DogEntity> commonDao; }
问题出在T.class这里会报错,自己试了几下不行,网上找了下如何获取泛型class,有说用内部类,有说用继承+反射,但其实还是要在封装类中传入具体类型,只不过再隔了一层,若要传入具体类型,那还要泛型干啥,固均不实用。看了spring的HibernateTemplate的get方法,也是需要用户传入具体类class的。固只能给findById方法增加参数,传入具体类class。
结论:
泛型只在编译期起作用,编译完成后由JVM的类型擦除机制(见引用)擦除泛型,运行期看不到泛型信息,已被替换为具体类型。(其实不是完全擦除,但泛型实现其实很复杂,我们不需要了解那么深,按这样理解就行!)
引用:
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
https://docs.spring.io/spring/docs/2.5.x/javadoc-api/org/springframework/orm/hibernate3/HibernateTemplate.html