基类中子类的Java泛型初始化

时间:2018-11-03 04:30:09

标签: java generics

我对Java还是很陌生,尤其不知道如何从“基”类初始化泛型类型/子类。
本质上,我有一堆扩展抽象类BaseClass的类,如果没有键,则需要初始化该抽象类并将其添加到instance Map中。
子类可重复使用多次,但会根据key参数动态创建。

我想避免反思,如果不是Java方式,也不要介意更改模板。
我目前有什么:

public abstract class BaseClass<T> {
    protected Map<String, T> instance = new HashMap<String, T>();

    public T Get(String key) {
        if (this.instance.containsKey(key)) {
            return this.instance.get(key);
        } 
        T item = new T(key); // Obviously this line errors but you get the idea
        instance.put(key, item);
        return item;
    }
}

// Example top class which extends my base class
public class TopClass extends BaseClass<TopClass> {
    public TopClass(String key) {
        // Do unique initialization stuff
    }
}

3 个答案:

答案 0 :(得分:1)

由于泛型类型在运行时被擦除,因此您不能这样做。您可以改为使用Class变量,如下所示:

public T Get(Class<T> clazz, String key) throws Exception {
    if (this.instance.containsKey(key)) {
        return this.instance.get(key);
    } 
    T item = clazz.getDeclaredConstructor(String.class).newInstance(key);
    instance.put(key, item);
    return item;
}

答案 1 :(得分:1)

泛型类型是未修饰的,在Java中作为Erasure实现。相反,反射在没有通用类型信息的运行时起作用。因此,您不知道此T在运行时意味着什么。这就是为什么您会遇到此编译器错误。

使用String作为对象图的键更容易出错。因此,您可以考虑使用类型标记。检查此更正的版本。

public class BaseClass {
    protected Map<Class<?>, Object> instance = new HashMap<>();

    @SuppressWarnings("unchecked")
    public <T> T Get(Class<?> key) {
        return (T) instance.computeIfAbsent(key, this::newInstance);
    }

    private Object newInstance(Class<?> type) {
        try {
            Constructor<?>[] constructors = type.getConstructors();
            Object[] args = null; // setup your constructor args here.
            return constructors[0].newInstance(args);
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}

在这种情况下,使类通用也显得有些尴尬。相反,您可以创建一个通用方法,并使用该方法在表中针对其类型存储任何实例。

答案 2 :(得分:1)

我对此有另一种方法。

具有接口MyInterface。

   public interface MyIinterface{
      public void doSomething();
   }

创建此接口的许多实现。

@Component
public class MyImplementation1 implements MyInterface{

    @Override
    public void doSomething(){

    }
}

在依赖项中使用spring core jars。

使用@Component注释所有实现。

@Component
public class MyImplementation1 implements MyInterface{
.
.

在某些Util类中有一个方法,该方法将为您提供基于字符串键的实现。

public static MyInterface getImplementation(String name){

  ApplicationContext context;
  return context.getBeanByName(name);

}