泛型擦除

一句话总结:泛型只在编译期生效!运行期不起作用!

 

先介绍问题,再引申到理论,比死记理论要好。最近要封装一个通用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

posted @ 2018-09-25 09:13  余正忠  阅读(275)  评论(0编辑  收藏  举报