Java 如何将泛型类型指定为函数参数

Java 如何将泛型类型指定为函数参数,java,generics,jpa,java-8,Java,Generics,Jpa,Java 8,我想为JSE应用程序创建一个返回结果的JPA事务 @SuppressWarnings("unchecked") public static <T> T transaction(EmWorker worker, Class<T>clazz){ EntityManager em = createEntityManager(); em.getTransaction().begin(); // >>> My Functional i

我想为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

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
List List=EmFactory.transaction(e->{
String query=“从FunkoPop f中选择f”;
List l=e.createQuery(query,FunkoPop.class).getResultList();
返回l;
},列表。类别)//不会编译;或List.class发出警告

事务
需要两个参数:lambda和class。我大致了解,我无法捕获类型
列表.class
,因为此参数将失去
泛型。没有警告的解决方案是什么?

您不能,因为没有
列表
类型。所有这些都有一个
列表

但是,您可能会采取艰难的方式:

List<T> transaction(EmWorker worker, Class<T>clazz) {
  ...
  List<T> l = (List<T>)e.createQuery(query, clazz).getResultList();
  return l;
}
列表事务(EmWorker,Classclazz){
...
List l=(List)e.createQuery(query,clazz).getResultList();
返回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;
}
公共静态接口EmListWorker{
公开列表工作(实体管理器em);
}
公共静态列表事务(EmListWorker,Classclazz){
EntityManager em=createEntityManager();
em.getTransaction().begin();
//>>>替代功能接口
列表结果=工人工作(em);
em.getTransaction().commit();
em.close();
返回结果;
}
使用@Holger提到的
功能
非常好。它的实现要简单得多:没有函数接口,也没有脏的强制转换。它返回一个选中的类型

实施:

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;
}
publicstatict事务(函数工作者){
EntityManager em=createEntityManager();
em.getTransaction().begin();
T结果=工人。应用(em);
em.getTransaction().commit();
em.close();
返回结果;
}
用法:

    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();
    });
funkopp gandalf=新的funkopp(“甘道夫”);
EmFactory.transaction(em->{
埃姆·帕斯蒂斯(甘道夫);
甘道夫归来;
});
列表=EmFactory.transaction(em->{
String query=“从FunkoPop f中选择f”;
返回em.createQuery(query,FunkoPop.class).getResultList();
});

您应该使用
clazz.cast(result)
而不是
(T)result
。然后,您不需要
@SuppressWarnings(“未选中”)
。不过,这只适用于可修改类型,而不适用于
List
。但是什么是EmWorker?将该类型设置为通用类型(或用
函数
替换)将消除所有这些特技。或者从一开始就使用
函数
并删除现在过时的
参数。这适用于所有类型。
    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();
    });