如何指定泛型类型作为函数参数
问题描述:
我想为返回结果的JSE应用程序创建JPA事务。如何指定泛型类型作为函数参数
@SuppressWarnings("unchecked")
public static <T> T transaction(EmWorker worker, Class<T>clazz){
EntityManager em = createEntityManager();
em.getTransaction().begin();
// >>> My Functional interface
Object result = worker.work(em);
em.getTransaction().commit();
em.close();
return (T)result;
}
它适用于读取单个对象:
FunkoPop gandalf=EmFactory.transaction( eManager -> {
return eManager.find(FunkoPop.class, 1);
}, FunkoPop.class);
但现在,我想的FunkoPop
一个List
。
List<FunkoPop> list =EmFactory.transaction( e -> {
String query = "SELECT f FROM FunkoPop f ";
List<FunkoPop> l = e.createQuery(query, FunkoPop.class).getResultList();
return l;
}, List<FunkoPop>.class); //Won't compile ; or List.class gives warnings
transaction
需要两个参数:lambda和class。我近似理解,我无法捕获类型List<FunkoPop>.class
,因为此参数将丢失通用的<FunkoPop>
。什么是没有警告的解决方案?
答
你不能因为没有List<FunkoPop>
类型。全部有List
。
您可以但是做硬盘的方式:
List<T> transaction(EmWorker worker, Class<T>clazz) {
...
List<T> l = (List<T>)e.createQuery(query, clazz).getResultList();
return l;
}
您可能需要重命名的方法。
答
添加第二个功能界面产生列表:
public static interface EmListWorker<T> {
public List<T> work(EntityManager em);
}
public static <T> List<T> transaction(EmListWorker<T> worker, Class<T>clazz){
EntityManager em = createEntityManager();
em.getTransaction().begin();
// >>> alternative Functional interface
List<T> result = worker.work(em);
em.getTransaction().commit();
em.close();
return result;
}
+2
或者仅从一开始就使用'Function
答
使用@Holger提到的是伟大的Function<EntityManager, T>
。实现起来要简单得多:没有功能接口,也没有脏话。并且它返回一个检查类型。
实现:
public static <T> T transaction(Function<EntityManager,T> worker){
EntityManager em = createEntityManager();
em.getTransaction().begin();
T result = worker.apply(em);
em.getTransaction().commit();
em.close();
return result;
}
用法:
FunkoPop gandalf = new FunkoPop("Gandalf");
EmFactory.transaction(em -> {
em.persist(gandalf);
return gandalf;
});
List<FunkoPop> list =EmFactory.transaction(em -> {
String query = "SELECT f FROM FunkoPop f ";
return em.createQuery(query, FunkoPop.class).getResultList();
});
你应该使用'clazz.cast(结果)'而非'(T)result'。然后,你不需要'@SuppressWarnings(“unchecked”)'。不过,这只适用于可授权类型,不适用于'List'。但是什么是EmWorker?制作该类型的泛型(或者用Function '替换它)将消除所有这些特技的需求。 –
Holger