递归打印对象详细信息

发布于 2024-09-27 14:05:47 字数 19 浏览 3 评论 0原文

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

How do I print the content of an object recursively?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

姐不稀罕 2024-10-04 14:05:47

您可以通过在所有类中重写 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();
}

You can print it recursively by overriding toString in all your classes.

If you want to have a method like printObjectRecursively(Object o) you need to dive into reflection, fetch the fields, print their name and content recursively using printObjectRecursively(someField).

Example:

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);
    }
}

Prints:

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

A reflection-based recursive print method could be written something like this

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();
}
一口甜 2024-10-04 14:05:47

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

单行递归:

ToStringBuilder.reflectionToString(obj, new RecursiveToStringStyle())

树状递归:

ToStringBuilder.reflectionToString(obj, new MultilineRecursiveToStringStyle())

Apache Common Lang contains ToStringBuilder class. You can define different style with ToStringStyle object.

Single line recursion:

ToStringBuilder.reflectionToString(obj, new RecursiveToStringStyle())

Tree-like recursion:

ToStringBuilder.reflectionToString(obj, new MultilineRecursiveToStringStyle())
挽你眉间 2024-10-04 14:05:47

我偶尔使用 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.
}

I've had great success doing this on a casual basis using XStream to dump JSON representations of objects. It recurses down objects and just seems to do what you want it to do most of the time. And it's super lightweight. Example:

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.
}
手心的温暖 2024-10-04 14:05:47

您正在寻找类似于 PHP 的 var_dump 的内容,看看这个问题是否有任何帮助: PHP var_dump 的 Java 等价物是什么?

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

You are looking for something similar to PHP's var_dump, see if this question is of any help: What is the Java equivalent of PHP var_dump?

Also, have a look at reflection: http://java.sun.com/developer/technicalArticles/ALT/Reflection/

小草泠泠 2024-10-04 14:05:47

使用序列化库之一,例如 Jackson (JSON)。

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

如果很多对象不可序列化,你可能会得到很多可读的乱码,这对任何事情都没有帮助,不幸的是,

YMMV

Use one of the serialization libraries like Jackson (JSON).

This dumps everything in plain text. If you use a Javascript capable editor to prettify the content, with a bit of luck, you might actually make some sense out of it.

If a lot of the objects are not serializable, you might end up with a lot of readable gibberish which will not help anything, unfortunately,

YMMV

何时共饮酒 2024-10-04 14:05:47

在某些情况下,使用Gson打印对象很容易。但有时gson不起作用。

在这里,我只是改进 aioobe 对这种情况的回答:

  • 不要打印打印对象(防止无限循环)
  • 打印集合
  • 不会深入了解几种基本类型,例如 BigInteger
    private static final Set<Object> looked = new HashSet<>();

    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, java.math.BigInteger.class, java.math.BigDecimal.class);

    public static void toStringRecursive(Object o, StringBuilder sb) throws Exception {
        if (o == null) {
            sb.append("null");
            return;
        }

        if (looked.contains(o)) return;
        looked.add(o);

        if (LEAVES.contains(o.getClass())) {
            sb.append(o);
            return;
        }

        sb.append(o.getClass().getSimpleName()).append(": [");
        if (o.getClass().isArray()) {
            for (Object x : (Object[]) o) {
                toStringRecursive(x, sb);
            }
        } else if (Iterable.class.isAssignableFrom(o.getClass())) {
            for (Object x : (Iterable) o) {
                toStringRecursive(x, sb);
            }
        } else if (Map.class.isAssignableFrom(o.getClass())) {
            for (Object entry : ((Map)o).entrySet()) {
                toStringRecursive(entry, sb);
            }
        } else {
            for (Field f : o.getClass().getDeclaredFields()) {
                if (Modifier.isStatic(f.getModifiers()))
                    continue;
                f.setAccessible(true);
                sb.append(f.getName()).append(": ");
                toStringRecursive(f.get(o), sb);
                sb.append(" ");
            }
        }
        sb.append("]\n");
    }

In some cases it is easy to use Gson to print object. But sometimes gson does not work.

Here I just improve aioobe' answer for this case:

  • don't print printed objects (protect from infinite cycles)
  • print collections
  • don't go deeply on few basic types, like BigInteger
    private static final Set<Object> looked = new HashSet<>();

    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, java.math.BigInteger.class, java.math.BigDecimal.class);

    public static void toStringRecursive(Object o, StringBuilder sb) throws Exception {
        if (o == null) {
            sb.append("null");
            return;
        }

        if (looked.contains(o)) return;
        looked.add(o);

        if (LEAVES.contains(o.getClass())) {
            sb.append(o);
            return;
        }

        sb.append(o.getClass().getSimpleName()).append(": [");
        if (o.getClass().isArray()) {
            for (Object x : (Object[]) o) {
                toStringRecursive(x, sb);
            }
        } else if (Iterable.class.isAssignableFrom(o.getClass())) {
            for (Object x : (Iterable) o) {
                toStringRecursive(x, sb);
            }
        } else if (Map.class.isAssignableFrom(o.getClass())) {
            for (Object entry : ((Map)o).entrySet()) {
                toStringRecursive(entry, sb);
            }
        } else {
            for (Field f : o.getClass().getDeclaredFields()) {
                if (Modifier.isStatic(f.getModifiers()))
                    continue;
                f.setAccessible(true);
                sb.append(f.getName()).append(": ");
                toStringRecursive(f.get(o), sb);
                sb.append(" ");
            }
        }
        sb.append("]\n");
    }
小霸王臭丫头 2024-10-04 14:05:47

您应该为您的类实现 toString 方法 - 它将打印有关类成员的信息 - 通常使用它们的 toString 方法。 |然后你只需迭代集合并调用每个项目的 toString

You should implement the toString method for your classes - it will print the information about the class members - usually using their toString methods. |Then you jut iterate through the collection and call toString of each item

丿*梦醉红颜 2024-10-04 14:05:47

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

Do you really need print this informations out? Maybe watch during debbuging will be enough?

终陌 2024-10-04 14:05:47

您可以重写 toString 方法。

示例:

class foo
{
 int i,j;

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

You can override the toString method.

Example:

class foo
{
 int i,j;

 String toString()
 {
 StringBuilder b=new StringBuilder();
 return b.append(i).append(j).toString();
 }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文