Eclipse has a handy template for automatically generating the toString() method for a class. You can access it by hitting Alt+Shift+S and clicking on "Generate toString()..."
From there you can you can choose which fields to include in your derived toString(), and set other options to determine how it should be generated.
I would like to use it to quickly generate toString() methods for a large amount of classes.
Take this example, here is a 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...
}
And here is an Album class which holds an array of Songs:
public class Album {
private Song[] songs;
private int songCount;
public Album(Song[] songs) {
this.songs = songs;
this.songCount = songs.length;
}
//getters...
}
I currently use this template to generate my toString() methods (with the "StringBuilder/StringBuffer - chained calls" option):
class ${object.className} {
${member.name}: ${member.value},
${otherMembers}
}
Which I can now use to generate the toString() for Song:
@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();
}
and for 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();
}
Now, let's say I create an album and want to test its toString() like this:
@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);
}
This is what I get:
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
}
But what I would like is a generator that can nest indentation, like this:
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
}
and continue to do so in the event of more classes inside each object, if that makes sense.
I tried to make a method that could replace a newline character with 4 spaces and a newline character before calling its toString():
private String indentString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
The idea being that it could turn "\n " in the append into "\n " and so on but I'm not sure if it's even possible to call a function inside the eclipse template.
Anyone have any clue on how to do this? I have checked the documentation but it's pretty sparse. Looked all over SO as well but I'm not seeing any similar questions.
For reference I am specifically using Spring Tool Suite version 4.0.1RELEASE.
It wasn't the way I was hoping to do it, but I do have a solution. I was able to accomplish what I wanted by creating a custom toString() builder class
Here is the class I created:
/*
* 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 ");
}
}
Then I can use Alt + Shift + S -> "Generate toString()..." and "select Custom toString() builder" and choose my CustomToStringBuilder. With this, Eclipse generates the following code for Song and Album:
//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();
}
Putting it all together and running my test again gives me my desired result:
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
}
However, I would still prefer a method that did not require adding a new class to the source code if possible so I'll leave the question open for a day or two to see if anyone can find a different way to do it more easily.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With