Предыстория: у меня есть приложение для весенней загрузки, которое получает входные параметры любого метода, аннотированного пользовательской аннотацией. Он помещает типы этих параметров в массив классов clazz, а значения — в массив объектов obj.
Это обобщено, поэтому элементы в obj могут быть массивами, например:
clazz = {int, java.lang.String, [D}
obj = {2, "Foobar", [3.1415, 2.718]}
Я пытаюсь распечатать все элементы в obj со следующим кодом. Обратите внимание, что clazz и obj всегда имеют одинаковую длину и одинаковые индексы связаны друг с другом (см. пример выше).
Код проверяет, является ли объект массивом, чтобы не печатать что-то вроде [D@431621
private void othermethod(Class[] clazz, Object[] obj){
for(int i =0 ; i<clazz.length;i++){
if (clazz[i].isArray()){
System.out.println(ObjArrayDisplay(obj[i], clazz[i]));
}
else{
System.out.println(obj[i].toString());
}
}
}
private String ObjArrayDisplay(Object o, Class c){
//Option 1. return Arrays.deepToString((Object[])o);java.lang.ClassCastException: [D cannot be cast to [Ljava.lang.Object;
//Option 2. return Arrays.deepToString(c.cast(o)); deepToString (java.lang.Object[]) in Arrays cannot be applied to (java.lang.Object)
}
И в этом заключается проблема.
Вернемся к примерам значений:
clazz = {int, java.lang.String, [D}
obj = {2, "Foobar", [3.1415, 2.718]}
Вариант 1: Для этого clazz и obj код компилируется, но когда код попадает в массив Double, его нельзя привести обратно к массиву Object, поскольку Double extends Object.
Вариант 2: на этот раз код даже не компилируется из-за синтаксической ошибки: Arrays.deepToString ожидает массив Object, но перед выполнением средство проверки синтаксиса видит только Object. Только после времени выполнения Double[], обернутый в объект, отправляется вниз по стеку.
Это также может быть проблемой с другими структурами данных, такими как Hashmap, ArrayList.
Есть ли способ получить элементы объекта o? У меня нет контроля над тем, какие примитивные типы или объекты являются входными данными для аннотированных методов, поэтому изменение clazz и obj не вариант.
Редактировать: Класс загрузки Spring, который предоставляет clazz (т.е. классы) и obj (т.е. параметры)
@Aspect
@Component
@Getter
public class Flow {
@Autowired
SubscriptionsIntegration SI;
private Class[] classes;
private Object[] params;
private Object returnvalue = "Start";
@Around("@annotation(TrackFlow)")
public Object TrackFlow(ProceedingJoinPoint joinPoint) throws Throwable{
CodeSignature cs = (CodeSignature) joinPoint.getSignature();
classes = cs.getParameterTypes();
params = joinPoint.getArgs();
Object proceed = joinPoint.proceed();
returnvalue = proceed;
return proceed;
}
}
Редактировать 2: Нашел решение в неясной зависимости maven и разместил его здесь.
Это вывод класса Spring Aspect с аннотацией @Around, который получает входные параметры из любого метода, аннотированного пользовательской аннотацией. Это рассматриваемый класс, который дает мне clazz и obj: Edit, теперь также добавлен в исходный пост.
AtAspect AtComponent AtGetter открытый класс Flow { @Autowired SubscriptionsIntegration SI; частные классы Class[]; частные параметры Object[]; частный объект returnvalue = "Старт"; @Around("@annotation(TrackFlow)") общедоступный объект TrackFlow(ProceedingJoinPoint joinPoint) throws Throwable{ CodeSignature cs = (CodeSignature) joinPoint.getSignature(); классы = cs.getParameterTypes(); params = joinPoint.getArgs(); Объект приступить = joinPoint.proceed(); возвращаемое значение = продолжить; возврат продолжить; } }




Если я правильно понимаю, вы можете использовать класс-оболочку и напечатать его toString
class Scratch {
public static void main(String[] args) {
Double[] objects = {2.02,2.22,2.13};
System.out.print(new Foo(objects));
String[] strings = {"array","of", "strings"};
System.out.print(new Foo(strings));
}
public static class Foo{
private Object[] objects;
public Foo(Object[] objects){
this.objects=objects;
}
@Override
public String toString() {
return "Foo{" +
"objects = " + Arrays.toString(objects) +
'}';
}
}
}
Вы упомянули, что не можете контролировать, являются ли это примитивами, но они не будут переданы в private void othermethod(Class[] clazz, Object[] obj), потому что они не будут массивом объектов.
Массив объектов obj может содержать что угодно, от примитивов до массивов объектов. В моем исходном посте я упомянул, что элемент obj, который является двойным массивом, не может быть приведен обратно в массив объектов из-за наследования.
Я не уверен, что понимаю. Double[] не является Object[], но Double[] является Object[]. Int примитивен, а Integer нет. Итак, если у вас есть метод с параметром объектов Object[] и вы попытались передать в него double[] doubles, он не скомпилируется
Да, вы технически правы насчет примитивов, хотя java преобразует примитивы, назначенные объектам, в их форму объекта, поэтому массив примитивов, приведенный к массиву объектов, функционально одинаков и будет компилироваться. В любом случае я нашел решение проблемы.
Нашел решение своего поста. Для справки в будущем, оказывается, есть зависимость Maven Jackson, которая может это сделать.
@Autowired
com.fasterxml.jackson.databind.ObjectMapper objectMapper;
//...other methods and variables
private String ObjArrayDisplay(Object o, Class c){
String returnValue = null;
try {
returnValue = objectMapper.writeValueAsString(o);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return returnValue;
}
Java — строго типизированный язык, поэтому делать что-то подобное всегда будет непросто. Чего именно вы пытаетесь достичь с помощью этих массивов clazz и object? Может быть, есть лучшая структура данных для их хранения?