具有嵌套缩进的 Eclipse toString() 生成器

Eclipse toString() generator with nested indentation

Eclipse 有一个方便的模板,可以自动为 class 生成 toString() 方法。您可以通过点击 Alt+Shift+S 并点击“Generate toString()...

来访问它

从那里您可以选择要包含在派生 toString() 中的字段,并设置其他选项以确定应如何生成它。

我想用它为大量 classes 快速生成 toString() 方法。

举个例子,这里有一个Song class:

public class Song {
    private String title;
    private int lengthInSeconds;
    public Song(String title, int lengthInSeconds) {
        this.title = title;
        this.lengthInSeconds = lengthInSeconds;
    }
    // getters and setters...

}

这是一个 Album class,它包含一个 Song 数组:

public class Album {
    private Song[] songs;
    private int songCount;
    public Album(Song[] songs) {
        this.songs = songs;
        this.songCount = songs.length;
    }
    //getters...

}

我目前使用此模板生成我的 toString() 方法(使用 "StringBuilder/StringBuffer - chained calls" 选项):

class ${object.className} {
    ${member.name}: ${member.value},
    ${otherMembers}
}

我现在可以使用它为 Song 生成 toString()

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("class Song {\n    ");
    if (title != null)
        builder.append("title: ").append(title).append(",\n    ");
    builder.append("lengthInSeconds: ").append(lengthInSeconds).append("\n}");
    return builder.toString();
}

Album:

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("class Album {\n    ");
    if (songs != null)
        builder.append("songs: ").append(Arrays.toString(songs)).append(",\n    ");
    builder.append("songCount: ").append(songCount).append("\n}");
    return builder.toString();
}

现在,假设我创建了一个相册并想像这样测试它的 toString()

@Test
public void testToString() {
    Song[] songs = new Song[] { 
            new Song("We Will Rock You", 200), 
            new Song("Beat it", 150),
            new Song("Piano Man", 400) };
    Album album = new Album(songs);
    System.out.println(album);
}

这是我得到的:

class Album {
    songs: [class Song {
    title: We Will Rock You,
    lengthInSeconds: 200
}, class Song {
    title: Beat it,
    lengthInSeconds: 150
}, class Song {
    title: Piano Man,
    lengthInSeconds: 400
}],
    songCount: 3
}

但我想要的是一个可以嵌套缩进的生成器,像这样:

class Album {
    songs: [class Song {
        title: We Will Rock You,
        lengthInSeconds: 200
    }, class Song {
        title: Beat it,
        lengthInSeconds: 150
    }, class Song {
        title: Piano Man,
        lengthInSeconds: 400
    }],
    songCount: 3
}

并在每个对象中有更多 class 的情况下继续这样做,如果这有意义的话。

我尝试制作一种方法,可以在调用 toString():

之前用 4 个空格和一个换行符替换一个换行符
private String indentString(java.lang.Object o) {
    if (o == null) {
        return "null";
    }
    return o.toString().replace("\n", "\n    ");
}

想法是它可以将追加中的 "\n " 变成 "\n " 等等,但我不确定是否可以在 eclipse 模板中调用函数。

有人知道如何执行此操作吗?我已经检查了文档,但它非常稀疏。也查看了所有内容,但我没有看到任何类似的问题。

作为参考,我专门使用 Spring 工具套件版本 4.0.1RELEASE。

这不是我希望的方式,但我确实有解决方案。我能够通过创建 custom toString() builder class

来完成我想要的

这是我创建的class:

/*
 * Helper class to generate formatted toString() methods for pojos
 */
public class CustomToStringBuilder {
    private StringBuilder builder;
    private Object o;

    public CustomToStringBuilder(Object o) {
         builder = new StringBuilder();
         this.o = o;
    }

    public CustomToStringBuilder appendItem(String s, Object o) {
        builder.append("    ").append(s).append(": ").append(toIndentedString(o)).append("\n");
        return this;
    }

    public String getString() {
        return "class " + o.getClass().getSimpleName() + "{ \n" + builder.toString() + "}";
    }

    /**
     * Convert the given object to string with each line indented by 4 spaces
     * (except the first line).
     */
    private static String toIndentedString(java.lang.Object o) {
        if (o == null) {
            return "null";
        }
        return o.toString().replace("\n", "\n    ");
    }
}

然后我可以使用 Alt + Shift + S -> "Generate toString()..." and "select Custom toString() builder ”并选择我的 CustomToStringBuilder。有了这个,Eclipse 为 SongAlbum 生成以下代码:

//Song
@Override
public String toString() {
    CustomToStringBuilder builder = new CustomToStringBuilder(this);
    builder.appendItem("title", title).appendItem("lengthInSeconds", lengthInSeconds);
    return builder.getString();
}

//Album
@Override
public String toString() {
    CustomToStringBuilder builder = new CustomToStringBuilder(this);
    builder.appendItem("songs", songs).appendItem("songCount", songCount);
    return builder.getString();
}

把它们放在一起 运行 我的测试又给了我想要的结果:

class Album{ 
    songs: [class Song{ 
        title: We Will Rock You
        lengthInSeconds: 200
    }, class Song{ 
        title: Beat it
        lengthInSeconds: 150
    }, class Song{ 
        title: Piano Man
        lengthInSeconds: 400
    }]
    songCount: 3
}

但是,如果可能的话,我仍然更喜欢一种不需要在源代码中添加新 class 的方法,所以我将问题悬而未决一两天,看看是否有人能找到一种更容易做到这一点的不同方法。