【问题标题】:Java generics: how to get a generic type from a method?Java泛型:如何从方法中获取泛型类型?
【发布时间】:2013-04-17 11:30:43
【问题描述】:

虽然我的问题是关于 Java 泛型的,但我已经放了一些与 JPA 相关的代码来向您展示真实的上下文。

我正在使用基于 JPA 2.0 和 Criteria API 的查询。我所有的查询都遵循相同的模式(比较简单的属性;不需要路径导航),所以我正在尝试编写一个通用类来处理 JPA,同时将业务逻辑保留在单独的类中。我的目标是有一个方法,给定一个实体类型和一个存储定义条件的对(字段名称 - > 所需值)的 Map,返回一个带有某些实体字段值的 bean(或 bean 集合) .

我所有的实体都实现了Persistible 接口,而我所有的传输对象都继承自QueryBean。我认为这些类与问题无关,所以我跳过了他们的代码。

以下代码是我第一种方法的 sn-p(请假设 cb 是有效的 CriteriaBuilder 实例):

protected <T extends QueryBean, TT extends Persistible> Collection<T> executeQueryEntity
        (Class<T> type, Class<TT> rootType, QueryConfig queryConfig, Map<String, Object> parameters) {
    // (...) Initialization goes here

    CriteriaQuery<T> c = cb.createQuery(type);

    // FROM CLAUSE
    Root<TT> root = c.from(rootType);

    // SELECT CLAUSE
    List<String> constructorParams = queryConfig.getTargetAttributes();
    Selection<?>[] selectArray = new Selection<?>[constructorParams.size()];
    for (int i = 0; i < constructorParams.size(); i++) {
        selectArray[i] = root.get(constructorParams.get(i));
    }
    c.select(cb.construct(type, selectArray));

    // WHERE CLAUSE
    for (String filter : parameters.keySet()) {
        if (queryConfig.getFieldConfiguration().get(filter).compareUsingEquals()) {
            // SOME PREDICATE
        }
        else {
            // SOME OTHER PREDICATE
        }
    }

    // (...) Rest of the code goes here
}

我的QueryConfig界面如下:

public interface QueryConfig {

List<String> getTargetAttributes();
Map<String, FieldConfiguration> getFieldConfiguration();

}

由于我已经在使用 QueryConfig 类,它提供有关查询的信息(例如 QueryBean 构造函数所需的参数或有关实体字段的信息),我认为从中获取实体类型会很好class 而不是将其作为 Class 参数传递。我从this 的问题推断它不能直接完成,所以我尝试了以下解决方法:

像这样向 QueryConfig 添加一个方法:

Class< ? extends Persistible> getTargetEntity();

像这样添加一个中间方法:

public <T extends QueryBean> Collection<T> queryMany(Class<T> type, QueryConfig config, Map<String, Object> parameters) {
    executeQueryEntity(type, config.getTargetEntity(), parameters);
}

但它不会编译。我相信这里解释了原因:Type mismatch for Class Generics 但我实际上并没有理解答案。 我的问题是:有没有办法避免将Class&lt; TT &gt; 参数传递给执行方法?这是处理问题的好方法还是我应该重构整个事情? 欢迎对代码进行任何改进!

【问题讨论】:

  • 顺便说一句,你的英语其实很好。实际上,在你指出之前,我什至没有注意到。
  • @Telthien 谢谢,我已经尽力了 =)
  • 你最好的传球比许多母语人士都好!真的很感激你的努力。

标签: java class generics types


【解决方案1】:

我不太明白您认为您的方法可行的原因: QueryConfigClass&lt; ? extends Persistible&gt; getTargetEntity(); 没有给出编译器可以引用的类型信息,为什么你认为编译器可以“猜测”你要返回的类型,并为你做类型检查?

一种方法是在 QueryConfig 中提供类型信息

public interface QueryConfig <T extends Persistable> {
  Class<T> getTargetEntity();
  List<String> getTargetAttributes();
  Map<String, FieldConfiguration> getFieldConfiguration();
}

您的 queryMany 方法可以是:

public <T extends QueryBean, TT extends Persistible> 
Collection<T> queryMany(Class<T> type, 
                        QueryConfig<TT> config, 
                        Map<String, Object> parameters) {
    executeQueryEntity(type, config.getTargetEntity(), parameters);
}

【讨论】:

  • 非常感谢!!我在尝试类似的东西,但是在queryMany的签名中错过了QueryConfig的类型参数,所以编译器抱怨从Class到Class的转换
猜你喜欢
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多