Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "ToString() generation"

(Planned features)
(Proposal for new toString template)
 
(4 intermediate revisions by one other user not shown)
Line 29: Line 29:
 
* Changing the output string format with templates [[Image:Ok_green.gif]]
 
* Changing the output string format with templates [[Image:Ok_green.gif]]
 
* Changing the order of the fields [[Image:Ok_green.gif]]
 
* Changing the order of the fields [[Image:Ok_green.gif]]
* User documentation (help)
+
* User documentation (help) [[Image:Ok_green.gif]]
* Unit tests [[Image:Progress.gif]]
+
* Unit tests [[Image:Ok_green.gif]]
  
 
=== Should have ===
 
=== Should have ===
Line 40: Line 40:
 
* Option to set the maximum number of elements to list from arrays/Collections (helping toString(...) methods)[[Image:Ok_green.gif]]
 
* Option to set the maximum number of elements to list from arrays/Collections (helping toString(...) methods)[[Image:Ok_green.gif]]
 
* Option to chose the insertion point of the method (as this is already there for equals() and hashCode()) [[Image:Ok_green.gif]]
 
* Option to chose the insertion point of the method (as this is already there for equals() and hashCode()) [[Image:Ok_green.gif]]
* Support multiple styles (per project option) [[Image:Progress.gif]]
+
* Support multiple styles (per project option) [[Image:Ok_green.gif]]
** Apache Commons-Lang ToStringBuilder
+
** Apache Commons-Lang ToStringBuilder [[Image:Ok_green.gif]]
** Spring Framework's ToStringCreator
+
** Apache Commons-Lang ToStringBuilder with chained method calls [[Image:Ok_green.gif]]
 +
** Spring Framework's ToStringCreator [[Image:Ok_green.gif]]
 +
** Spring Framework's ToStringCreator with chained method calls[[Image:Ok_green.gif]]
 
** String concatenation [[Image:Ok_green.gif]]
 
** String concatenation [[Image:Ok_green.gif]]
 
** StringBuilder/StringBuffer [[Image:Ok_green.gif]]
 
** StringBuilder/StringBuffer [[Image:Ok_green.gif]]
** String.format()
+
** StringBuilder/StringBuffer with chained method calls [[Image:Ok_green.gif]]
** Single return value (e.g. if only one field is chosen, for existing primary keys or Objects with 'names')
+
** String.format() [[Image:Ok_green.gif]]
 +
** <strike>Single return value (e.g. if only one field is chosen, for existing primary keys or Objects with 'names')</strike>
  
 
=== Nice to have ===
 
=== Nice to have ===
  
* Ability to add different implementations of the toString generator or use multiple code templates (e.g. extension points)
+
* Ability to add different implementations of the toString generator or use multiple code templates (e.g. extension points) [[Image:Ok_green.gif]]
 
* <strike>Change hashCode and equals generators to optionally use getters</strike>
 
* <strike>Change hashCode and equals generators to optionally use getters</strike>
 
** Change hashCode and equals generators to support <strike>inherited</strike> fields and methods
 
** Change hashCode and equals generators to support <strike>inherited</strike> fields and methods
* Annotations (would require Java5 though)
+
* Annotations (would require Java5 though)[[Image:Ok_green.gif]]
 
* Refactorings if e.g. a field is renamed/removed/added (consider save actions. mark fields for permanent exclusion by)
 
* Refactorings if e.g. a field is renamed/removed/added (consider save actions. mark fields for permanent exclusion by)
 
* NLS support (if desirable in toString)
 
* NLS support (if desirable in toString)
Line 67: Line 70:
  
 
* Nice to have: Accessible through quickfix/content assistant
 
* Nice to have: Accessible through quickfix/content assistant
* Nice to have: Support options for include/exclude hashcode, super.toString(), class name, use System.identityHashCode() or Object's hashCode()
+
* Nice to have: Support options for include/exclude hashcode, super.toString(), class name, use System.identityHashCode() or Object's hashCode() [[Image:Ok_green.gif]] (controled with templates)
 
* Nice to have: Integration with [http://www.javalobby.org/java/forums/t16350.html Detail Formatters] from the Debugger
 
* Nice to have: Integration with [http://www.javalobby.org/java/forums/t16350.html Detail Formatters] from the Debugger
  
Line 107: Line 110:
 
* Still easy to add new fields manually if desired
 
* Still easy to add new fields manually if desired
 
* Bad to see which fields are associated with which variables, as they are far apart
 
* Bad to see which fields are associated with which variables, as they are far apart
 +
 +
==== Proposal for new Code Template ====
 +
 +
This proposal addresses a some minor issues with the current solutions.
 +
 +
* Enhanced flexibility.
 +
* Enhanced clarity of code.
 +
* Provides for localised toString methods.
 +
* Exploits flexibility of StringFormat() will performance of StringBuilder
 +
 +
<source lang="java">
 +
public class StringBuilderExample {
 +
private final Locale locale = Locale.getDefault();
 +
private final String aString = "aStringValue";
 +
public static final double π = java.lang.StrictMath.PI;
 +
private final Double aDouble = 0.499999999999999917;
 +
private final int aMaxInt = Integer.MAX_VALUE;
 +
private final int aMinInt = Integer.MAX_VALUE;
 +
private final boolean isTrue = true;
 +
private final boolean isFalse = false;
 +
 +
    /**
 +
    * Implements toString in a better way.
 +
    *
 +
    * @return the class properties as String Object.
 +
    */
 +
    public String toStringBetter()
 +
    {
 +
        StringBuilder stringBuilder = new StringBuilder();
 +
        stringBuilder.append(String.format("aString=%s, ",this.aString))
 +
        .append(String.format("π=%f(%s), ",π,π))
 +
        .append(String.format("aDouble=%f(%s), ",this.aDouble,this.aDouble))
 +
        .append(String.format("aMaxInt=%s, ",this.aMaxInt))
 +
        .append(String.format("aMinInt=%s, ",this.aMinInt))
 +
        .append(String.format("isTrue=%s, ",this.isTrue))
 +
        .append(String.format("isFalse=%s ",this.isFalse));
 +
        return String.format(this.locale,"%s [%s %s]",
 +
                                this.getClass().getSimpleName(),
 +
                                super.toString(),
 +
                                stringBuilder.toString());
 +
    }
 +
 +
    public static void main(String[] args) {
 +
    final StringBuilderExample stringBuilderExample = new StringBuilderExample();
 +
    System.out.println(stringBuilderExample.toStringBetter());
 +
}
 +
 +
}
 +
</source>
  
 
== Getting the source ==
 
== Getting the source ==
  
 
For source code, check the latest patch submitted to {{bug|26070}}.  
 
For source code, check the latest patch submitted to {{bug|26070}}.  
 +
 +
Also, a plug-in version is available: [[Media:Org.gsoc.eclipse.tostringgenerator_1.0.0.zip‎]]
 +
  
 
[[Category:SOC]]
 
[[Category:SOC]]

Latest revision as of 07:52, 5 November 2013

About

The toString() method is widely used to represent objects as human-readable text and practically every class should implement it. Usually it is very simple: generated string contains the object type and lists values of the most important fields. That's why process of writing such methods can easilly be automated. Eclipse, as the best java IDE in the world, should include functionality of automatic toString() method generation to make its users lives even simpler. Implementing it is the aim of this project.

There were many bugs posted regarding this problem, see bug 26070 for details.

This project is part of 2008 Google Summer of Code.

Participants:

  • CVS: dev.eclipse.org/cvsroot/technology/org.eclipse.soc/.../ (TBD)

Planned features

  • Legend
Glass.gif Needs some investigation
Progress.gif Patch in progress
Ok green.gif Bug fixed / Feature added

Must have

  • Integration with 'Generate hashCode() and equals()' dialog
  • Turning generators on/off separately
  • Changing the output string format with templates Ok green.gif
  • Changing the order of the fields Ok green.gif
  • User documentation (help) Ok green.gif
  • Unit tests Ok green.gif

Should have

  • Option to use getters instead of accessing the fields directly
    • Using fields as well as methods (including getters), also inherited ones Ok green.gif
  • Option to skip fields with null value Ok green.gif
  • Option to ignore default toString() of arrays and list elements instead (using Arrays.toString()) Ok green.gif
  • Option to set the maximum number of elements to list from arrays/Collections (helping toString(...) methods)Ok green.gif
  • Option to chose the insertion point of the method (as this is already there for equals() and hashCode()) Ok green.gif
  • Support multiple styles (per project option) Ok green.gif
    • Apache Commons-Lang ToStringBuilder Ok green.gif
    • Apache Commons-Lang ToStringBuilder with chained method calls Ok green.gif
    • Spring Framework's ToStringCreator Ok green.gif
    • Spring Framework's ToStringCreator with chained method callsOk green.gif
    • String concatenation Ok green.gif
    • StringBuilder/StringBuffer Ok green.gif
    • StringBuilder/StringBuffer with chained method calls Ok green.gif
    • String.format() Ok green.gif
    • Single return value (e.g. if only one field is chosen, for existing primary keys or Objects with 'names')

Nice to have

  • Ability to add different implementations of the toString generator or use multiple code templates (e.g. extension points) Ok green.gif
  • Change hashCode and equals generators to optionally use getters
    • Change hashCode and equals generators to support inherited fields and methods
  • Annotations (would require Java5 though)Ok green.gif
  • Refactorings if e.g. a field is renamed/removed/added (consider save actions. mark fields for permanent exclusion by)
  • NLS support (if desirable in toString)

Glossary

  • Code Template: The template used to generate the method signature and body of the toString() method
  • Output String Format: The format of the String generated by the implementation of the toString() method

Community proposals

Feel free to add your ideas

  • Nice to have: Accessible through quickfix/content assistant
  • Nice to have: Support options for include/exclude hashcode, super.toString(), class name, use System.identityHashCode() or Object's hashCode() Ok green.gif (controled with templates)
  • Nice to have: Integration with Detail Formatters from the Debugger

Code Template suggestion 1

An example for an easily editable format:

public String toString()
{
    return super.toString ()
        + " (field=" + field
        + ", field2=" + field2
        + ")"
    ;
}

This allows to reorder lines by moving (and replacing " (" with ", " in one-of-many cases). Faster than using StringBuilder() or any other way. Fields can be added and removed with least amount of fuzz. Code and result is readable for humans. No ambiguity of result (only "null" and null can't be told apart). Also, the format is easily parsable if you want to offer a "do it again" dialog.

Things to keep in mind:

  • The current formatter (where to put blanks and the curly braces)
  • Use the field directly or call the getter. Direct access is faster but breaks when a getter is overloaded in a subclass.

--Digulla.hepe.com 07:23, 15 May 2008 (EDT)

Code Template suggestion 2

public String toString()
{
    return String.format("%s[field=%s, field2=%s]", super.toString(), field, field2);
}
  • Reordering of fields is done in the dialog and the toString() method is regenerated
  • No String concatenation required
  • Still easy to add new fields manually if desired
  • Bad to see which fields are associated with which variables, as they are far apart

Proposal for new Code Template

This proposal addresses a some minor issues with the current solutions.

  • Enhanced flexibility.
  • Enhanced clarity of code.
  • Provides for localised toString methods.
  • Exploits flexibility of StringFormat() will performance of StringBuilder
public class StringBuilderExample {
	private final Locale locale = Locale.getDefault();
	private final String aString = "aStringValue";
	public static final double π = java.lang.StrictMath.PI;
	private final Double aDouble = 0.499999999999999917;
	private final int aMaxInt = Integer.MAX_VALUE;
	private final int aMinInt = Integer.MAX_VALUE;
	private final boolean isTrue = true;
	private final boolean isFalse = false;
 
    /**
     * Implements toString in a better way.
     *
     * @return the class properties as String Object.
     */
    public String toStringBetter()
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(String.format("aString=%s, ",this.aString))
        				.append(String.format("π=%f(%s), ",π,π))
        				.append(String.format("aDouble=%f(%s), ",this.aDouble,this.aDouble))
        				.append(String.format("aMaxInt=%s, ",this.aMaxInt))
        				.append(String.format("aMinInt=%s, ",this.aMinInt))
        				.append(String.format("isTrue=%s, ",this.isTrue))
        				.append(String.format("isFalse=%s ",this.isFalse));
        return String.format(this.locale,"%s [%s %s]",
                                this.getClass().getSimpleName(),
                                super.toString(),
                                stringBuilder.toString());
    }
 
    public static void main(String[] args) {
    	final StringBuilderExample stringBuilderExample = new StringBuilderExample();
    	System.out.println(stringBuilderExample.toStringBetter());
	}
 
}

Getting the source

For source code, check the latest patch submitted to bug 26070.

Also, a plug-in version is available: Media:Org.gsoc.eclipse.tostringgenerator_1.0.0.zip‎

Copyright © Eclipse Foundation, Inc. All Rights Reserved.