Динамическое приведение объектов из массива объектов к соответствующим классам, доступным в перечислении
public class A {
private String property;
public String getProperty() {
return property;
}
}
public class B {
private String property;
public String getProperty() {
return property;
}
}
аналогично определяются классы C и D.(Опуская другую логику и сложность)
Затем создал перечисление этих имен классов.[Простое имя класса или каноническое имя класса, которое я могу добавить без проблем]
public enum ClassNameEnum{ A, B, C, D }
В другом классе у меня есть массив Object, который содержит экземпляры любого из перечисленных классов.
Моя цель: получить каждый элемент в массиве объектов, привести их к одному из имен classe в myEnum и выполнить вызов метода.
Что я сделал до сих пор. (1) перебрать массив объектов и иметь лестницу для проверки instanceof. Если соответствует, приведите и сделайте операцию [работает, но уродливо]
(2) Улучшение:
public class ImplClass {
public static void main(String[] args)
{
List<Object> objectList = new ArrayList<Object>();
objectList.add(new B());
objectList.add(new D());
objectList.add(new A());
for (Object object : objectList) {
Arrays.asList(ClassNameEnum.values()).stream()
.filter(e -> obj instanceof e) // Error here: e cannot be resolved to a type
.map(e -> (e)obj)
.map("Call getProperty() on the casted object and return the string"); // This is what I want to do
}
}
}
заранее спасибо
2 ответа
Вместо enum вы можете хранить классы в структуре вроде:
class ClassInfo<T> {
private final Class<T> clazz;
private final Function<T, String> function;
// all args constructor here
String castAndApply(Object obj) {
return function.apply(clazz.cast(obj));
}
}
затем создайте карту, например:
Map<Class, ClassInfo> classInfos = Map.of(
A.class, new ClassInfo<>(A.class, A::getA),
B.class, new ClassInfo<>(B.class, B::getB),
C.class, new ClassInfo<>(C.class, C::getProperty)
);
и ниже это использование:
objectList.stream()
.filter(obj -> classInfos.containsKey(obj.getClass()))
.map(obj -> classInfos.get(obj.getClass()).castAndApply(obj))
.forEach(System.out::println);
Поскольку вы хотите вызывать общий метод для всех ваших объектов, имеет смысл создать здесь интерфейс.
public interface Property {
String getProperty();
}
И в вашем классе:
public class A implement Property {
private String property;
@Override
public String getProperty() {
return property;
}
}
Попробуйте сохранить ваш объект по ссылке на интерфейс:
List<Property> objectList = new ArrayList<>();
objectList.add(new A());
objectList.add(new B());
...
И наконец:
objectList.forEach(o -> System.out.println(o.getProperty()));