【问题标题】:Java Access array elements from an object array containing an object containing a double array in IntellijJava从包含Intellij中包含双精度数组的对象的对象数组中访问数组元素
【发布时间】:2019-02-07 19:59:28
【问题描述】:

背景故事:我有一个 Spring Boot 应用程序,它可以获取使用自定义注释进行注释的任何方法的输入参数。它将这些参数的类型放在类数组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 扩展了 Object。

选项 2:由于语法错误,这次代码甚至无法编译:Arrays.deepToString 需要一个 Object 数组,但在运行前语法检查器只能看到 Object。直到运行时之后,包装在 Object 中的 Double[] 才被发送到堆栈中。

这对于 Hashmap、ArrayList 等其他数据结构也会有问题。

有没有办法获取Object o的元素?我无法控制哪些原始类型或对象是带注释的方法的输入,因此不能选择更改 clazz 和 obj。

编辑:提供clazz(即类)和obj(即参数)的Spring boot类

@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 依赖项中找到了解决方案,并在此处发布。

【问题讨论】:

  • Java 是一种强类型语言,所以做这样的事情总是很棘手。你到底想用这些 clazz 和 object 数组来实现什么?也许有更好的数据结构来存储它们?
  • 它是带有 @Around 注释的 Spring Aspect 类的输出,它从使用自定义注释注释的任何方法获取输入参数。这是给我 clazz 和 obj 的问题类:编辑,现在也添加到原始帖子中
  • AtAspect AtComponent AtGetter public class Flow { @Autowired SubscriptionsIntegration SI;私有类[] 类;私有对象 [] 参数;私有对象返回值=“开始”; @Around("@annotation(TrackFlow)") public Object TrackFlow(ProceedingJoinPoint joinPoint) throws Throwable{ CodeSignature cs = (CodeSignature) joinPoint.getSignature();类 = cs.getParameterTypes();参数 = joinPoint.getArgs();对象进行 = joinPoint.proceed();返回值 = 继续;返回继续; } }

标签: java spring maven spring-boot intellij-idea


【解决方案1】:

为我自己的帖子找到了解决方案。为了将来参考,原来有一个 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;
}

【讨论】:

    【解决方案2】:

    如果我理解正确,您可以使用包装类并将其打印为 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 将分配给对象的原语转换为其对象形式,因此转换为对象数组的原语数组在功能上是相同的并且可以编译。无论如何,我找到了解决问题的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多