【问题标题】:Java Generics and Reflection | How to instantiate a generic classJava 泛型和反射 |如何实例化一个泛型类
【发布时间】:2016-05-13 17:10:06
【问题描述】:

现在是星期五晚上,所以我可能有点慢,但我无法弄清楚我认为这是一个简单的问题。

我基本都是这种情况。

1) 一个基类 MyDAO

public abstract class MyDAO<K, E> implements DAO<K, E> 
{
   ....
}

2) 给定包中的一堆 MyDAO 具体类实现,比如:

public class TaxonomyDAO extends MyDAO<Integer,Taxonomy>{

    ....
}

每个扩展 MyDAO 的类基本上都将特定的 DAO 特性添加到它们的 E 元素中。我正在编写一个通用工厂,其目标是在此类存在时使用反射来提供 WhatClassDAO 的实例,如果不存在则返回基本 MyDAO。假设 K 始终为整数。

我写过这样的东西:

public Object getDAOForEntity(Class c)
    {
        createEmfa();

        try {
            Class eDao = Class.forName(getClass().getPackage().getName()+c.getSimpleName()+"DAO");
            Constructor<?> cons = eDao.getConstructor(EntityManagerFactory.class);            
            return cons.newInstance(emfa);
        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
            return new MyDAO<Integer,?????>(emfa) {};

        }         
    }

这个类,给定一个Class c(比如WhateverClass),尝试使用反射来使用参数化构造函数创建WhateverClassDAO 的实例。 ***DAO 类被假定在工厂的同一个包中(我尽量保持简单,以便在此处发布)。

在捕获中,由于反射失败,我假设没有 WhateverClassDAO,所以我想返回一个 MyDAO&lt;Integer,WhateverClass&gt; 但我无法在那里传递正确的 E 参数。我尝试将Class&lt;E&gt; 作为参数传递,但没有成功。我基本上想知道用什么来代替??????。

它超出了范围,但所有这些代码都在单例 EJB 中。

任何帮助,即使是正确文档的链接,我们都将不胜感激。

【问题讨论】:

  • 只有 Chuck Norris 可以在 java 中实例化抽象类。
  • 我希望我没有冒犯。开个玩笑;)如果不存在这样的 DAO,我会返回一个可选的缺席。
  • 我猜你可以在运行时创建子类并将其注册到 Spring 的依赖注入机制,但这将是一个挑战
  • 无意冒犯,我也自嘲了:)

标签: java generics reflection syntax


【解决方案1】:

Class 类也是泛型的,您可以从中推断出正确的泛型参数:

public <E> Object getDAOForEntity(Class<E> c) {
    try {
        // ...
    } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
        return new MyDAO<Integer,E>(emfa) {};
    }
}

【讨论】:

  • 我之前试过了,忘记了方法声明开头的类型声明...这里是晚上7.20...休息一下。谢谢你的快速回答:)
【解决方案2】:

你应该创建一个泛型方法,并且最好让它返回你的 dao 基类而不是 Object:

  public <E> MyDAO<Integer, E> getDAOForEntity(Class<E> c) {
    ...
    try {
      Class<MyDAO<Integer, E>> eDao = (Class<MyDAO<Integer, E>>)(Class<?>)Class.forName(getClass().getPackage().getName()+c.getSimpleName()+"DAO");
      Constructor<MyDAO<Integer, E>> cons = eDao.getConstructor(EntityManagerFactory.class);            
      return cons.newInstance(emfa);
    } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
      return new MyDAO<Integer,E>(emfa) {};
    }         
  }

【讨论】:

  • 我要退回那个。我在发布之前快速编辑了代码。类名也不是那些
  • 好。也为了摆脱演员的警告,你可以添加 @SuppressWarnings("unchecked")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多