我对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
}
}
答案 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);
}