Один метод решения требует типа должны быть переданы в:
private Map<Class<?>, Map<String, Object>> instanceMaps;
public <T> T getInstance(String key,
Class<T> instanceType) {
if (instanceMaps == null) {
instanceMaps = new HashMap<>();
instanceMaps.put(ClassA.class, instanceAMap);
instanceMaps.put(ClassB.class, instanceBMap);
instanceMaps.put(ClassC.class, instanceCMap);
}
Map<String, Object> instanceMap = instanceMaps.get(instanceType);
if (instanceMap == null) {
throw new IllegalArgumentException("Unknown type: " + instanceType);
}
Object value = instanceMap.get(key);
if (value == null) {
try {
instanceMap.put(key, value = instanceType.newInstance());
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(e);
}
}
return instanceType.cast(value);
}
instanceAMap, instanceBMap и instanceCMap все должны быть объявлены как Map<String, Object>
. Невозможно извлечь разные конкретные типы из одной карты или коллекции.
Лично я бы не пытался принудительно использовать один метод, но использовал бы перегруженные методы, которые можно было бы реорганизовать в один частный общий метод. Это позволяет instanceAMap быть объявлен как Map<String, ClassA>
и т. Д. Для примераBMap и instanceCMap.
private <T> T getInstance(String key,
Map<String, T> instanceMap,
Supplier<T> constructor) {
return instanceMap.computeIfAbsent(key, k -> constructor.get());
}
public ClassA getInstanceA(String key) {
return getInstance(key, instanceAMap, ClassA::new);
}
public ClassB getInstanceB(String key) {
return getInstance(key, instanceBMap, ClassB::new);
}
public ClassC getInstanceC(String key) {
return getInstance(key, instanceCMap, ClassC::new);
}
В версиях старше Java 8, выше, можно записать в виде:
private <T> T getInstance(String key,
Map<String, T> instanceMap,
Class<T> instanceType) {
T value = instanceMap.get(key);
if (value == null) {
try {
instanceMap.put(key, value = instanceType.newInstance());
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(e);
}
}
return value;
}
public ClassA getInstanceA(String key) {
return getInstance(key, instanceAMap, ClassA.class);
}
public ClassB getInstanceB(String key) {
return getInstance(key, instanceBMap, ClassB.class);
}
public ClassC getInstanceC(String key) {
return getInstance(key, instanceCMap, ClassC.class);
}
Как @ user902383 сказал, что было бы полезно, если бы вы могли использовать одну карту, чтобы держать все объекты и ключи , но, очевидно, это потребует гарантии того, что ни один из двух классов никогда не будет использовать один и тот же ключ:
public <T> T getInstance(String key,
Class<T> instanceType) {
Object value = instanceMap.get(key);
if (value != null) {
return instanceType.cast(value);
}
try {
T newValue = instanceType.newInstance();
instanceMap.put(key, newValue);
return newValue;
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(e);
}
}
Уверен, что все эти классы имеют доступный конструктор no-arg? – Seelenvirtuose
любая причина, почему ваш класс имеет 3 разных карты? можете ли вы реорганизовать это и иметь одну карту? – user902383
@Seelenvirtuose Нет, классы могут иметь любые конструкторы, это просто пример. –