相关文章推荐
暴躁的石榴  ·  翻译 - Dolibarr ERP CRM ...·  5 月前    · 
不羁的饺子  ·  Debezium | Apache Flink·  5 月前    · 
讲道义的烈酒  ·  Debezium-JSON--流式计算 ...·  5 月前    · 
从容的大脸猫  ·  零代码第三方数据接入 | TDengine ...·  5 月前    · 
迷茫的马克杯  ·  从VBA中的范围中删除特殊字符开发者社区·  5 月前    · 
慷慨大方的番茄  ·  揭秘潮汕帮金融帝国 ...·  8 月前    · 
还单身的红金鱼  ·  Kingbase V8R6 ...·  9 月前    · 
失恋的薯片  ·  中影股份IPO拟募46亿:垄断红利渐失·  2 年前    · 
逼格高的小虾米  ·  仙剑奇侠传电视剧一共几部 – 快看漫画问答·  3 年前    · 
魁梧的白开水  ·  GitHub Copilot 文档 - ...·  3 年前    · 
Code  ›  转储java对象的属性开发者社区
string
https://cloud.tencent.com/developer/ask/sof/65261
开朗的长颈鹿
3 年前
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
提问
问 转储java对象的属性
Stack Overflow用户
提问于 2009-03-02 16:38:01
EN

是否有一个库可以递归地转储/打印对象属性?我正在寻找类似于Firebug中的 console.dir() 函数的东西。

我知道commons-lang ReflectionToStringBuilder ,但它不会递归到对象中。也就是说,如果我运行以下命令:

public class ToString {
    public static void main(String [] args) {
        System.out.println(ReflectionToStringBuilder.toString(new Outer(), ToStringStyle.MULTI_LINE_STYLE));
    private static class Outer {
        private int intValue = 5;
        private Inner innerValue = new Inner();
    private static class Inner {
        private String stringValue = "foo";
}

我收到:

外部字符串$

@1b67f74 intValue=5

innerValue=ToString$Inner@530daa

我意识到,在我的示例中,我可以覆盖内部的toString()方法,但在现实世界中,我正在处理无法修改的外部对象。

10 76.9K 0 票数 69
EN
java
reflection
properties
dump
tostring

回答 10

Stack Overflow用户

回答已采纳

发布于 2009-03-02 16:48:36

你可以试试 XStream 。

XStream xstream = new XStream(new Sun14ReflectionProvider(
  new FieldDictionary(new ImmutableFieldKeySorter())),
  new DomDriver("utf-8"));
System.out.println(xstream.toXML(new Outer()));

打印输出:

<foo.ToString_-Outer>
  <intValue>5</intValue>
  <innerValue>
    <stringValue>foo</stringValue>
  </innerValue>
</foo.ToString_-Outer>

您还可以在 JSON 中输出

并注意循环引用;)

票数 43
EN

Stack Overflow用户

发布于 2011-11-15 23:22:57

我尝试按照最初的建议使用XStream,但我想转储的对象图包含了对XStream封送处理程序本身的引用,这并不是很友好(我不确定为什么它必须抛出异常而不是忽略它或记录一个很好的警告。)

然后我尝试了上面user519500中的代码,但发现我需要一些调整。这里有一个类,你可以将它放入一个项目中,它提供了以下额外的功能:

  • 可以控制最大递归深度
  • 可以限制数组元素输出
  • 可以忽略任何类、字段或class+field组合的列表-只需传递包含类名、冒号分隔的classname+fieldname对或带有冒号前缀的字段名的任意组合的数组即: [<classname>][:<fieldname>]
  • Will不输出同一对象两次(输出指示对象以前被访问的时间,并提供用于关联的哈希码)-这避免了循环引用导致的问题

您可以使用以下两种方法中的一种来调用它:

    String dump = Dumper.dump(myObject);
    String dump = Dumper.dump(myObject, maxDepth, maxArrayElements, ignoreList);

如上所述,您需要小心堆栈溢出,因此使用最大递归深度工具将风险降至最低。

希望有人会发现这很有用!

package com.mycompany.myproject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.HashMap;
public class Dumper {
    private static Dumper instance = new Dumper();
    protected static Dumper getInstance() {
        return instance;
    class DumpContext {
        int maxDepth = 0;
        int maxArrayElements = 0;
        int callCount = 0;
        HashMap<String, String> ignoreList = new HashMap<String, String>();
        HashMap<Object, Integer> visited = new HashMap<Object, Integer>();
    public static String dump(Object o) {
        return dump(o, 0, 0, null);
    public static String dump(Object o, int maxDepth, int maxArrayElements, String[] ignoreList) {
        DumpContext ctx = Dumper.getInstance().new DumpContext();
        ctx.maxDepth = maxDepth;
        ctx.maxArrayElements = maxArrayElements;
        if (ignoreList != null) {
            for (int i = 0; i < Array.getLength(ignoreList); i++) {
                int colonIdx = ignoreList[i].indexOf(':');
                if (colonIdx == -1)
                    ignoreList[i] = ignoreList[i] + ":";
                ctx.ignoreList.put(ignoreList[i], ignoreList[i]);
        return dump(o, ctx);
    protected static String dump(Object o, DumpContext ctx) {
        if (o == null) {
            return "<null>";
        ctx.callCount++;
        StringBuffer tabs = new StringBuffer();
        for (int k = 0; k < ctx.callCount; k++) {
            tabs.append("\t");
        StringBuffer buffer = new StringBuffer();
        Class oClass = o.getClass();
        String oSimpleName = getSimpleNameWithoutArrayQualifier(oClass);
        if (ctx.ignoreList.get(oSimpleName + ":") != null)
            return "<Ignored>";
        if (oClass.isArray()) {
            buffer.append("\n");
            buffer.append(tabs.toString().substring(1));
            buffer.append("[\n");
            int rowCount = ctx.maxArrayElements == 0 ? Array.getLength(o) : Math.min(ctx.maxArrayElements, Array.getLength(o));
            for (int i = 0; i < rowCount; i++) {
                buffer.append(tabs.toString());
                try {
                    Object value = Array.get(o, i);
                    buffer.append(dumpValue(value, ctx));
                } catch (Exception e) {
                    buffer.append(e.getMessage());
                if (i < Array.getLength(o) - 1)
                    buffer.append(",");
                buffer.append("\n");
            if (rowCount < Array.getLength(o)) {
                buffer.append(tabs.toString());
                buffer.append(Array.getLength(o) - rowCount + " more array elements...");
                buffer.append("\n");
            buffer.append(tabs.toString().substring(1));
            buffer.append("]");
        } else {
            buffer.append("\n");
            buffer.append(tabs.toString().substring(1));
            buffer.append("{\n");
            buffer.append(tabs.toString());
            buffer.append("hashCode: " + o.hashCode());
            buffer.append("\n");
            while (oClass != null && oClass != Object.class) {
                Field[] fields = oClass.getDeclaredFields();
                if (ctx.ignoreList.get(oClass.getSimpleName()) == null) {
                    if (oClass != o.getClass()) {
                        buffer.append(tabs.toString().substring(1));
                        buffer.append("  Inherited from superclass " + oSimpleName + ":\n");
                    for (int i = 0; i < fields.length; i++) {
                        String fSimpleName = getSimpleNameWithoutArrayQualifier(fields[i].getType());
                        String fName = fields[i].getName();
                        fields[i].setAccessible(true);
                        buffer.append(tabs.toString());
                        buffer.append(fName + "(" + fSimpleName + ")");
                        buffer.append("=");
                        if (ctx.ignoreList.get(":" + fName) == null &&
                            ctx.ignoreList.get(fSimpleName + ":" + fName) == null &&
                            ctx.ignoreList.get(fSimpleName + ":") == null) {
                            try {
                                Object value = fields[i].get(o);
                                buffer.append(dumpValue(value, ctx));
                            } catch (Exception e) {
                                buffer.append(e.getMessage());
                            buffer.append("\n");
                        else {
                            buffer.append("<Ignored>");
                            buffer.append("\n");
                    oClass = oClass.getSuperclass();
                    oSimpleName = oClass.getSimpleName();
                else {
                    oClass = null;
                    oSimpleName = "";
            buffer.append(tabs.toString().substring(1));
            buffer.append("}");
        ctx.callCount--;
        return buffer.toString();
    protected static String dumpValue(Object value, DumpContext ctx) {
        if (value == null) {
            return "<null>";
        if (value.getClass().isPrimitive() ||
            value.getClass() == java.lang.Short.class ||
            value.getClass() == java.lang.Long.class ||
            value.getClass() == java.lang.String.class ||
            value.getClass() == java.lang.Integer.class ||
            value.getClass() == java.lang.Float.class ||
            value.getClass() == java.lang.Byte.class ||
            value.getClass() == java.lang.Character.class ||
            value.getClass() == java.lang.Double.class ||
            value.getClass() == java.lang.Boolean.class ||
            value.getClass() == java.util.Date.class ||
            value.getClass().isEnum()) {
            return value.toString();
        } else {
            Integer visitedIndex = ctx.visited.get(value);
            if (visitedIndex == null) {
                ctx.visited.put(value, ctx.callCount);
                if (ctx.maxDepth == 0 || ctx.callCount < ctx.maxDepth) {
                    return dump(value, ctx);
                else {
                    return "<Reached max recursion depth>";
            else {
                return "<Previously visited - see hashCode " + value.hashCode() + ">";
    private static String getSimpleNameWithoutArrayQualifier(Class clazz) {
        String simpleName = clazz.getSimpleName();
        int indexOfBracket = simpleName.indexOf('['); 
        if (indexOfBracket != -1)
            return simpleName.substring(0, indexOfBracket);
        return simpleName;
}
票数 41
EN

Stack Overflow用户

发布于 2009-05-18 20:23:24

您可以将ReflectionToStringBuilder与自定义ToStringStyle一起使用,例如:

class MyStyle extends ToStringStyle {
    private final static ToStringStyle instance = new MyStyle();
    public MyStyle() {
        setArrayContentDetail(true);
        setUseShortClassName(true);
        setUseClassName(false);
        setUseIdentityHashCode(false);
        setFieldSeparator(", " + SystemUtils.LINE_SEPARATOR + "  ");
    public static ToStringStyle getInstance() {
        return instance;
    @Override
    public void appendDetail(StringBuffer buffer, String fieldName, Object value) {
        if (!value.getClass().getName().startsWith("java")) {
            buffer.append(ReflectionToStringBuilder.toString(value, instance));
        } else {
            super.appendDetail(buffer, fieldName, value);
 
推荐文章
暴躁的石榴  ·  翻译 - Dolibarr ERP CRM Wiki
5 月前
不羁的饺子  ·  Debezium | Apache Flink
5 月前
讲道义的烈酒  ·  Debezium-JSON--流式计算 Flink版-火山引擎
5 月前
从容的大脸猫  ·  零代码第三方数据接入 | TDengine 文档 | 涛思数据
5 月前
迷茫的马克杯  ·  从VBA中的范围中删除特殊字符开发者社区
5 月前
慷慨大方的番茄  ·  揭秘潮汕帮金融帝国 四大家族资产超万亿_美中时报 美中经贸的桥梁 精英人士的智库
8 月前
还单身的红金鱼  ·  Kingbase V8R6 事务中发生错误,跳过继续执行_com.kingbase8.util.ksqlexception: error: current t-CSDN博客
9 月前
失恋的薯片  ·  中影股份IPO拟募46亿:垄断红利渐失
2 年前
逼格高的小虾米  ·  仙剑奇侠传电视剧一共几部 – 快看漫画问答
3 年前
魁梧的白开水  ·  GitHub Copilot 文档 - GitHub 文档
3 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号