11
\$\begingroup\$

I would like to ask those of you, who are a little bit more expirienced in development. I would like to ask about toString() method usage. In what situations do you use it?

I've found some info about it, for example here, but it's not what I'm looking for.

Is there any convension which says when should I use it for my custom objects? In model layer or in view? Let me show a simple example...

I've got a class called "Component". Component has some name, values etc... One of the fields can be a perfect information for the user about object's state. The rest is also important, but not nessesary to display on the screen (in a view layer). Moreover, this field is a String and should be translated depending on the language settings. It's also required to present this field as an upperCase().

So, the question is: Should I put all the logic connected with forming a "user-friendly" string (locals, upperCase...) in a toString() method? Or maybe I should create a getUserFriendlyName() method instead and use toString(), for instance, for debugging (so in model). So, should toString() method have any influence on what the end user can see on the screen?

    @Override
    public String toString() {
        String toReturn;
        try {
            toReturn = language.getString("LOCAL_STRING_KEY_" + this.compInfo);
        } catch (MissingResourceException e) {
            logger.warning("No key found for " + compInfo);
            toReturn = this.compInfo;
        }
        return toReturn;
    }
\$\endgroup\$
1
  • \$\begingroup\$ Post actual code, please. What is the content of 'compInfo'? I'm guessing it's some kind of naming scheme for services. JNDI resource name, etc? \$\endgroup\$ Commented Nov 29, 2013 at 10:17

2 Answers 2

11
\$\begingroup\$

Is there any convension which says when should I use it for my custom objects? In model layer or in view?

If your question is 'When should I override the default toString() method and use create my own?' then there is one set of answers. If your question is 'when should I call the toString() method (implicitly like "This is my object: " + myobj or explicitly)?' then there is a different set of answers.

So, when should you override the toString()? From the Javadoc for Object:

In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.

I strongly agree with this statement. Every custom class you create should override the toString method, and should find a way to textually represent the class content in a meaningful (but not necessarily exhaustive) way. For example, a 'Point' class representing a co-ordinate x and y where x==3 and y==4 should return something like Point(3,4). On the other hand, I believe that some classes are over-exhaustive with toString, like ArrayList does too much. I would prefer ArrayList(size 10: [sample0 .... sample9]). Edit: The Java tutorial for Object also says the same thing about toString():

The Object's toString() method returns a String representation of the object, which is very useful for debugging

The reasons for making every class have a toString is because of the times you should use the toString() method.... and, as far as I am concerned, there are only three places in general programming where using toString() is legitimate (and two 'special' cases):

  1. In exception handling: throw new IllegalStateException("Failed to process " + value);
  2. for logging program progress using things like log4j.
  3. when the JavaDoc for the toString() Method for the class you are using defines a specific, and non-alterable format for the result. e.g. String.toString() or Integer.toString(). If the class you are using does not specify what the toString() returns, and does not guarantee that it won't change, then create your own way to present the data.

There are two special cases for using toString():

  1. I think, even though this is a special case, that this is the most important reason: when running your Java program through a debugger like the one built in to Eclipse. When you are stepping through your program the debugger will use the toString() method to show you the state of all your variables. This is where, in many cases, you will value the toString() more than anything else.
  2. when developing or debugging a program it is often convenient for you to add 'println' statements, and they can be things like: System.out.println("Processing customer " + customer);`

In summary, the toString() method should produce enough data to debug problems with the object content. It is used occasionally for a 'contractual' representation of a value (like String.toString()).

But, in general, toString() Is a tool for the PROGRAMMER, not for the user. It is there to assist you when things go wrong, not when they go right.

In my real Job I file bugs against code (and pursue the bugs relentlessly) which throws exceptions where the exception has an Object.toString() in the message. I also mentally +1 people who's programs produce good detail during exceptional conditions.

Now, in your particular situation, I think that you should use the toString() method to represent the state of your Customer, and, because the display-conditions for your customer are different to the internal state (e.g. display needs to be UPPERCASE,) I think that you should have a different mechanism for displaying the Customer than the toString() method.

In other words, the information you will need to debug a situation involving a Customer (something printed in a stack trace or debug session) is different than the information you want to display on the screen.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Thanks! "But, in general, toString() Is a tool for the PROGRAMMER, not for the user" - this is exactly what I wanted to know. \$\endgroup\$
    – radekEm
    Commented Nov 29, 2013 at 13:04
  • \$\begingroup\$ Exceptions should only be seen by the programmer too, so I'm curious as to why you would think toString() should not be used from those. \$\endgroup\$
    – Hakanai
    Commented Jan 6, 2017 at 3:28
  • \$\begingroup\$ @Trejkaz - It may not be as clear as it should be, but when I say "I file bugs against code ... which throws exceptions where the exception has an Object.toString() in the message" I mean exceptions that have the raw output from toString() from the Object base class.... i.e. not an overridden toString(). e.g. It is a bug if an exception has things like Illegal characters in: my.class.Name@106d69c instead of Illegal characters in: "Joe Blogs!!" \$\endgroup\$
    – rolfl
    Commented Jan 6, 2017 at 5:33
  • \$\begingroup\$ Ah, that makes sense then. Those default toString() methods Java put in, I wonder why they thought that was better than, say, a dump of the fields and their values. :/ \$\endgroup\$
    – Hakanai
    Commented Jan 7, 2017 at 5:46
3
\$\begingroup\$

You usually place it in your model, so when you invoke .toString() on an object you get a string representation of the object.

How your string representation looks like can be up to you. Here is an example where I return a simple JSON-formatted string representation of my object Foo

public class Foo {

    private string name;
    private int id;

    public Foo(string name, int id) {
        this.name = name;
        this.id = id;
    }

    @override
    public string toString() {
        return "{name: " + this.name + ", id:" + this.id + "}";
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.