8

I just started learning Java. What I've learned about constructor is that :

  1. It will automatically run when an object is initialized.

  2. The name of the constructor has be the same as the class name.

Now, below is where I'm starting to get confused.

class Frog{

   public String toString() {
      return "Hello";
   }
}

public class App {

   public static void main(String[] args) {
      Frog frog1 = new Frog();
      System.out.println(frog1);
   }
}

My question : Since public String toString () is not a constructor, then why can it behave like constructor when I run the program. I thought It can only be run when I call it from the App class.

Vipin Jain
  • 3,686
  • 16
  • 35
Bernard
  • 83
  • 1
  • 4
  • 1
    Since you have not defined a constructor for class Frog, Java compiler adds a "default constructor", that is automatically generated by the compiler. toString is automatically called for the frog1 Object constructed by the default constructor. – Costis Aivalis Mar 21 '16 at 10:34
  • See http://stackoverflow.com/questions/8555771/why-is-the-tostring-method-being-called-when-i-print-an-object? – Raedwald Mar 26 '16 at 14:06

7 Answers7

22

Short answer: public frog1.toString() method call is used inside System.out.println(Object x) call stack.

But how? Let's find it out together :)

Take a look at the PrintStream class (which instance is used as System.out field value by default) source code and its println implementation that accepts Object argument:

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

And the String's valueOf method for argument with Object type is:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

obj is frog1 in your case, its toString() method is called and returns "Hello" String instance for the console output)

Cootri
  • 3,806
  • 20
  • 30
  • 3
    Exactly. `System.out.println(frog1)` implies a call to the `toString()` method. The same happens when you do something like `final String aString = "This is a " + frog1;` – Alex Mar 21 '16 at 10:31
  • but I don't specifically call frog1.toString(), I just call frog1. – Bernard Mar 21 '16 at 10:33
  • what if I have multiple methods in the Frog class? Doesn't that mean I have to specify which methods to call? – Bernard Mar 21 '16 at 10:35
  • 2
    @Bernard No, only the method with the exact name toString() will be called by `System.out.println(Object obj);` when you put in `frog1`, as explained by _Cootri_. Try renaming your toString() method to `test()` for example and see how the output of `System.out.println(frog1);` changes. Since you've got a method `public String toString()` you've basically overwritten the default Object's toString() method. (All classes automatically extend Object, enabling the use of some default Object-methods like toString() and getType().) – Kevin Cruijssen Mar 21 '16 at 10:37
  • @Bernard What do you think will happen when `System.out.println(frog1);` gets executed? `Frog` is not `String` you see and hence it will invoke `toString()` on it. Since you have overridden the `toString()` method to return `Hello` it will print it on the console. – user2004685 Mar 21 '16 at 10:42
  • 2
    Thanks @KevinCruijssen, to be honest as a java beginner I can't really understand the example posted by Cootri until KevinCruijissen shed light on it with simpler explanation. And also thanks to all of bro's that have helped with additional explanation. – Bernard Mar 21 '16 at 12:38
3

The "toString" is not behaving like a constructor; the reason why it is being called is the second line in your main method:

  System.out.println(frog1);

This invokes toString on frog1.

Andrea Bergia
  • 5,502
  • 1
  • 23
  • 38
1

When you call PrintStream class print(obj) / println(obj) method then internally it called write method with arguement as String.valueOf(obj) shown below :

public void print(Object obj) {
    write(String.valueOf(obj));
} 

Now String.valueOf(obj) does the task of calling to String method as shown below :

 /** 
 * Returns the string representation of the <code>Object</code> argument. 
 * 
 * @param   obj   an <code>Object</code>. 
 * @return  if the argument is <code>null</code>, then a string equal to 
 *          <code>"null"</code>; otherwise, the value of 
 *          <code>obj.toString()</code> is returned. 
 * @see     java.lang.Object#toString() 
 */ 
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
} 
Vipin Jain
  • 3,686
  • 16
  • 35
0

public String toString(){..} is method of class Object , here overridden specifically for Frog class. This method returns object value representation. It's a method not a constructor. Please remember constructor cannot return value.

Valid constructor would be something like below:

 public Frog(){}
Dark Knight
  • 8,218
  • 4
  • 39
  • 58
0

The toString method overrides Object.toString

public String toString() {
      return "Hello";
}

So when call

 System.out.println(frog1);

It toString's the object to "hello"

M. Suurland
  • 725
  • 12
  • 31
0

The usage of toString is to give some meaningful representation for your class. Something like description about the object or class can go inside toString method.

Whenever the object is used with any String referenced operations like System.out.print or String s="abcd"+frog1;" the content of toString will be returned.

If toString is not overridden it would return the object class and its hash code. Please check here

From your code,

  • Frog frog1 = new Frog(); => creates object frog1 of type Frog.
  • System.out.println(frog1); => outputs the String representation
    of the object frog1.

Hope it explains.

Community
  • 1
  • 1
Sridhar
  • 1,832
  • 3
  • 23
  • 44
0

I'm not sure you understand what "behaving like a constructor" means. The Frog constructor (the default one, because you haven't written one) is called when you do new Frog(). The call to .toString() is done automatically inside the call to .println(), which is in the line after the call to the constructor.

You may be getting confused because toString() is the only method you have declared. However, you are missing the knowledge that there is an implicit default constructor automatically in your class. If you were to type it out it would look like this:

public Frog() {
    // default constructor does nothing
}

It is that default constructor that is "behaving like a constructor". toString() is just behaving like a method that is being called by another method (the key thing being that println(Object o) is definitely certain that Object has a toString() method because it is part of the class definition).

Rikki
  • 1,142
  • 15
  • 17