【问题标题】:Recursively print an objects details递归打印对象详细信息
【发布时间】:2010-10-11 10:34:08
【问题描述】:

如何递归打印对象的内容?

【问题讨论】:

  • 与您的问题相同,我将回答“使用递归方法”。

标签: java recursion


【解决方案1】:

您可以通过在所有类中覆盖 toString 来递归打印它。

如果你想拥有像printObjectRecursively(Object o) 这样的方法,你需要深入思考,获取字段,使用printObjectRecursively(someField) 递归地打印它们的名称和内容。

例子:

public class Test {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a);
    }
}

class A {
    int i = 5;
    B obj = new B();
    String str = "hello";
    public String toString() {
        return String.format("A: [i: %d, obj: %s, str: %s]", i, obj, str);
    }
}

class B {
    int j = 17;
    public String toString() {
        return String.format("B: [j: %d]", j);
    }
}

打印:

A: [i: 5, obj: B: [j: 17], str: hello]

基于反射的递归打印方法可以这样写

private static final List LEAVES = Arrays.asList(
        Boolean.class, Character.class, Byte.class, Short.class,
        Integer.class, Long.class, Float.class, Double.class, Void.class,
        String.class);

public static String toStringRecursive(Object o) throws Exception {

    if (o == null)
        return "null";

    if (LEAVES.contains(o.getClass()))
        return o.toString();

    StringBuilder sb = new StringBuilder();
    sb.append(o.getClass().getSimpleName()).append(": [");
    for (Field f : o.getClass().getDeclaredFields()) {
        if (Modifier.isStatic(f.getModifiers()))
            continue;
        f.setAccessible(true);
        sb.append(f.getName()).append(": ");
        sb.append(toStringRecursive(f.get(o))).append(" ");
    }
    sb.append("]");
    return sb.toString();
}

【讨论】:

  • 这个方法给了我一个stackoverflowError :)
  • @KjetilNordin 是对的,应尽可能避免递归。关于 DZone 的精彩阅读:dzone.com/articles/…(“折叠宇宙”文章)。
  • @Benj,这大概是因为 KjetilNordin 在他的图表中有一个循环。如果以迭代的方式天真地完成此操作,程序将不会终止(或由于 OOME 而崩溃)。我认为用递归来解决这类问题是非常好的。
  • @aioobe,我同意这个过程不应该出现在“日常对象”上,但我尽量避免递归(但这是恕我直言)。我完全同意您出于调试目的的代码,您为非循环图提供了一个聪明的解决方案。我从昨天开始使用它,工作正常,谢谢:)
【解决方案2】:

你可以使用:

ToStringBuilder.reflectionToString(this);

Apache Common Lang 包含ToStringBuilder 类。您可以使用ToStringStyle 对象定义不同的样式。

【讨论】:

    【解决方案3】:

    我在随意使用 XStream 转储对象的 JSON 表示的基础上取得了巨大的成功。它递归了对象,并且似乎在大多数情况下都在做您希望它做的事情。而且它超级轻巧。示例:

    private static final XStream jsonXStream = 
        new XStream(new JsonHierarchicalStreamDriver());
    
    public static String toDebugString(Object object) {
        return jsonXStream.toXML(object);  
        // ignore "toXML" name, it's going to be JSON.
    }
    

    【讨论】:

      【解决方案4】:

      您应该为您的类实现toString 方法——它将打印关于类成员的信息——通常使用他们的toString 方法。 |然后你遍历集合并调用每个项目的toString

      【讨论】:

        【解决方案5】:

        您真的需要打印这些信息吗?也许在调试期间观看就足够了?

        【讨论】:

          【解决方案6】:

          你正在寻找类似于 PHP 的 var_dump 的东西,看看这个问题是否有帮助:What is the Java equivalent of PHP var_dump?

          另外,看看反射:http://java.sun.com/developer/technicalArticles/ALT/Reflection/

          【讨论】:

            【解决方案7】:

            您可以覆盖 toString 方法。

            示例:

            class foo
            {
             int i,j;
            
             String toString()
             {
             StringBuilder b=new StringBuilder();
             return b.append(i).append(j).toString();
             }
            }
            

            【讨论】:

              【解决方案8】:

              使用Jackson (JSON) 等序列化库之一。

              这会将所有内容转储为纯文本。如果您使用支持 Javascript 的编辑器来美化内容,运气好的话,您实际上可能会理解它。

              如果很多对象是不可序列化的,你可能会得到很多可读的乱码,很遗憾,这无济于事,

              YMMV

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-10-23
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-07-27
                • 2021-06-26
                相关资源
                最近更新 更多