我如何通过" T"使用Java泛型作为方法参数的参数?

时间:2014-04-28 17:20:29

标签: java generics instantiation

我正在使用JBoss 7.1.3和Java 6.我无法在下面的代码中找出我需要替换“???”以使我的方法正常工作。我想要的是实例化我的“T”类的实例,每次实例化该类时都调用泛型构造函数。以下是方法......

public class MyClass<T extends AbstractModel>
{

    public void myMethod()
    {
        …
        final HashMap<String, String> data = new HashMap<String, String>();
        final T item = getInstance(???, data);

    }


    private T getInstance(final Class<T> class1,
                  final HashMap<String, String> data)
    {
        T retObj = null;
        try
        {
            Constructor ct = class1.getDeclaredConstructor(HashMap.class);
            Object[] argList = new Object[1];
            argList[0] = data;
            retObj = (T) ct.newInstance(argList);
        } catch (Exception e)
        {
        }   // try
        return retObj;
    }   // getInstance

这是我的抽象模型类的构造函数...

public abstract class AbstractDIDOModel 
{

    protected HashMap<String, String> data;

    AbstractModel(final HashMap<String, String> data) 
    { 
        this.data = data;
    }

2 个答案:

答案 0 :(得分:1)

MyClass应该传递Class<T>

public class MyClass<T extends AbstractModel>
{
    private final Class<T> type;

    public MyClass(Class<T> type) { this.type = type; }

    public void myMethod()
    {
        …
        final HashMap<String, String> data = new HashMap<String, String>();
        final T item = getInstance(type, data);

    }

由于Type Erasure,运行时不存在T的信息,因此在大多数情况下您无法获得它所引用的类型。

另请注意,Constructor已键入,因此您可以将其替换为:

Constructor ct = class1.getDeclaredConstructor(HashMap.class);
//...
retObj = (T) ct.newInstance(argList);

有了这个:

Constructor<T> ct = class1.getDeclaredConstructor(HashMap.class);
//...
retObj = ct.newInstance(argList);

如果你的目标是使用Class<T>作为工厂,我会采取不同的方法。我只接受Factory<T>,其中Factory<T>是一个界面:

public interface Factory<T extends AbstractModel> {
   T create(HashMap<String, String> data);
}

然后MyClass<T>的创建者可以简单地实现这一点,而不必诉诸于反射:

Factory<ConcreteModel> factory = new Factory<ConcreteModel>() {
   @Override
   public ConcreteModel create(HashMap<String, String> data) {
        return new ConcreteModel(data);
   }
}

答案 1 :(得分:0)

如果您的类具有类型参数集,则可以使用技巧,因为在这种情况下,类型信息在运行时可用。您可以捕获它并将其存储在成员字段中。然后,您可以将该字段用作通用构造方法中的类。

public abstract class AbstractDIDOModel<T> 
{

 private Class<?> persistentClass = (Class<?>) ((ParameterizedType)  this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

 private T getInstance(final HashMap<String, String> data)
    {
        T retObj = null;
        try
        {
            Constructor ct = persistentClass.getDeclaredConstructor(HashMap.class);
            Object[] argList = new Object[1];
            argList[0] = data;
            retObj = (T) ct.newInstance(argList);
        } catch (Exception e)
        {
        }   // try
        return retObj;
    }

最后,声明你的具体类:

public class MyClass<T extends AbstractModel>
{
   ....
}