java - Java中对象在内存中的字段和值遍历

标签 java json object

我有一个场景,我需要遍历内存中的复杂对象。我需要遍历整个树的键和值以及所需的内容。有什么办法可以做到吗?它无法序列化为 JSON,这是一个大问题。所以唯一的方法就是当对象加载到内存中时遍历该对象。

enter image description here

对象实际上看起来像这样。它可能有很深的嵌套,并且 GSON 或任何其他库无法将其序列化为 JSON。

最佳答案

非常非常复杂。

给定任何对象,获取其所有字段:

Class<?> c = obj.getClass();
var fields = new ArrayList<Field>();
while (c != null) {
   for (Field f : c.getDeclaredFields()) {
       if (Modifier.isStatic(f.getModifiers())) continue;
       f.setAccessible(true);
       fields.add(f);
    }
    c = c.getSuperclass();
}

看起来工作量很大,但您还必须使用 declaredFields 变体来获取私有(private)字段,并且它不会自动为您遍历父类(super class)型层次结构。获得该列表后,您可以使用通常的 field.get(obj) 获取该字段的对象集。然后..将相同的算法递归地应用于这些对象以构建这样的层次结构。

问题:数组

数组需要特别小心。你不能只向它询问它的字段;你还可以向它询问它的字段。它不会有。因此,在使用 field.get(obj) 后,您需要这个:

if (a.getClass().isArray()) {
    int len = Array.getLength(a);
    for (int i = 0; i < len; i++) {
        Object actualContent = Array.get(a, i);
    }
}

然后将“actualContent”的每个值视为正常值(即递归地对其运行此算法)。

问题:需要打印大量内容!

是的,确实如此——单独的字符串内部就有一个char[]。您可能想要对已知类型(例如String)进行一些instanceof检查和“硬编码”自定义打印机。

问题:JDK11+ 发出警告。

是的,最终这将不再被允许,并且在不连接调试器代理的情况下没有办法可以做到这一点,这是一种更复杂的蠕虫。从 JDK14 开始,即使它打印警告,这仍然有效。

问题:循环/自引用

对象可以在循环中引用自身。例如:

List<Object> list = new ArrayList<Object>();
list.add(list);

// or a cycle:

List<Object> list1 = new ArrayList<Object>();
List<Object> list2 = new ArrayList<Object>();
list1.add(list2);
list2.add(list1);

这会导致你的打印代码永远循环。解决这个问题的方法是跟踪对象身份,如果您发现一个已经“见过”的对象,则根本不打印它,而只打印一些引用。这还要求您打印每个对象的引用。要获取标识对象的数字,请使用 System.identityHashCode,它保证会很好地尝试为您提供唯一的 id(但不能 100% 保证每个对象一定会获得唯一的 ID)。要检查您是否已经看到一个对象,请使用 IdentityHashMap,其中映射的值部分并不重要(如果有一个 IdentityHashSet 我会告诉您使用那个,但没有。只需映射到“”并检查 key 是否存在)。

考虑所有这些事情,您也可以编写一个深入的对象打印机。

或者只是依靠您的 IDE 来完成此操作,对于任何让您遇到的问题,可能都有更好的解决方案:我知道!我将递归地打印该对象的全部原始内容! – 但你的问题不包括你为什么想要这个。

关于java - Java中对象在内存中的字段和值遍历,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61069630/

相关文章:

javascript - 将对象数组分组为特定格式

python - 使用链接列表时出现错误 : <__main__. 位于 0x03A5F990> 的节点对象

java - 在 Java 中存储和解析 HTML 时出现特殊字符和符号问题

java - 当我尝试将有效的代码带入类中时,它会出现错误

c# - 使用 JSON.NET 将 JSON 反序列化为匿名对象

php - 在php中必须从jquery [object Object]获取数据

javascript将对象复制到引用的内存中

java - 我如何处理 Undertow 中的 HTTP 方法?

java - 通过 URL 路径 POST/PUT 与 JAX-RS Jersey 中的参数

json - 解析错误 : Invalid numeric literal at line 1, 第 2 列 (bash)