About toString:by: Nicholas DuchonDate: Jun 23, 2015 |
Outline: |
public String toString () method
After looking up toString with google, I am really unhappy with
the information I have found.
First, what if we create a class and do not implement a toString method? Well, here's an example:
MyClass x = new MyClass ();
System.out.println (x);
MyClass@70dea4e
NOTE: the System.out.println (x) - the parameter here is just the variable of type MyClass - and the Java system interprets this to mean that it should convert the instance x of the class MyClass to a string representation using MyClass's toString method. This is the way Java works.
Gruesome (you can skip this part if you don't understand it yet):
So what is this? This is the default toString method from the
Object class, the parent class of all classes in Java. It is not
completely obvious, but the first field here is the name of the
class. The second field is a kind of random number, the hash code
for this instance of the class MyClass as it's instantiated.
What happens if we provide a toString method? NOTE: this is a special method that is:
I have seen at least one example (the tutorialspoint.com site)
that talks as if toString (int) is the same kind of method. That
is NOT the case, such a method does not override the method in
Object, and will not be called in the case of code such as
System.out.println (x).
Continuing - what if we implement a toString method, as per the requirements listed in the bullet points above? Here's an example (quite trivial):
return "This is the String representation of a MyClass object";
MyClass x = new MyClass ();
System.out.println (x);
This is the String representation of a MyClass object
Now, what if the class actually has interesting data fields? How might toString be used?
The point of toString is that it must return a String of some sort, and is typically used to return a useful representation of the instance variables of a class:
int a = 12;
double b = 4.554;
char c = '#';
String d = "Invincible";
boolean e = true;
String f;
return String.format (
"%d, %f, %c, %s, %b, %s",
a, b, c, d, e, f);
MyClass x = new MyClass ();
System.out.println (x);
12, 4.554000, #, Invincible, true, null
One key point here is that the code in main (System.out.println
(x)) has NOT changed in all these examples - only the code inside
the toString method has changed (and the new instance variables in
the last example).
Next, to understand just how flexible this approach is, the following toString implementation returns the same output as the one just above:
String st = "";
st += a + ", ";
st += b + ", ";
st += c + ", ";
st += d + ", ";
st += e + ", ";
st += f;
return st;
You may have noticed that this code does not explicity convert
any of these primitive data types to a String. So, the Java system
is in fact calling toString methods appropriate to each object.
For example, the details work like this: a is an int, the system
automatically converts this to an Integer object, and then calls
the toString method in the Integer class. Another example of just
how powerful the concepts of toString and method overriding are in
Java.
As with all examples, you will get the most out of these if you
experiment with them yourself.
There are more, and more interesting, examples of toString
methods in many of the examples on the following pages:
I think you will start to understand a lot more about how
toString might work with data structures in the following example.
Here we are considering a 2D integer array with some numbers:
public class ArrayTestA {
public static void main (String args []) {
int n = 5, m = 3;
int x [] [] = new int [n][m];
for (int i = 0; i < x.length; i++)
for (int j = 0; j < x[i].length; j++)
x[i][j] = i*j - 5 * i + 12 * j;
for (int [] r: x) {
for (int v: r)
System.out.printf ("%5d", v);
System.out.println ();
} // end for each row
System.out.println (java.util.Arrays.toString (x));
System.out.println (java.util.Arrays.deepToString (x));
} // end main
} // end class ArrayTestA
Output: 0 12 24
-5 8 21
-10 4 18
-15 0 15
-20 -4 12
[[I@70dea4e, [I@5c647e05, [I@33909752, [I@55f96302, [I@3d4eac69]
[[0, 12, 24], [-5, 8, 21], [-10, 4, 18], [-15, 0, 15], [-20, -4, 12]]
The yellow hightlighted code is now calling the toString method
of the ArrayTestB class, and it is that toString method which is
walking through the instance variable x (the 2D array).
public class ArrayTestB {
int x [] [];
public ArrayTestB (int n, int m) {
x = new int [n][m];
for (int i = 0; i < x.length; i++)
for (int j = 0; j < x[i].length; j++)
x[i][j] = i*j - 5 * i + 12 * j;
} // end int/int constructor
public String toString () {
String st = "";
for (int [] r: x) {
for (int v: r)
st += String.format ("%5d", v);
st += "\n";
} // end for each row
return st;
} // end method toString
public static void main (String args []) {
ArrayTestB atb = new ArrayTestB (5, 3);
System.out.println ("Arrays.toString:\n" + java.util.Arrays.toString (atb.x));
System.out.println ("\nArrays.deepToString:\n" + java.util.Arrays.deepToString (atb.x));
System.out.println ("\nArrayTestB toString:\n" + atb );
} // end main
} // end class ArrayTestB
OUTPUT:
Arrays.toString:
[[I@70dea4e, [I@5c647e05, [I@33909752, [I@55f96302, [I@3d4eac69]
Arrays.deepToString:
[[0, 12, 24], [-5, 8, 21], [-10, 4, 18], [-15, 0, 15], [-20, -4, 12]]
ArrayTestB toString:
0 12 24
-5 8 21
-10 4 18
-15 0 15
-20 -4 12
next?