The connection between 'System.out.println()' and 'toString()' in Java
System.out
is a PrintStream
. Printstream defines several versions of the println()
function to handle numbers, strings, and so on. When you call PrintStream.println()
with an arbitrary object as a parameter, you get the version of the function that acts on an Object
. This version of the function
...calls at first String.valueOf(x) to get the printed object's string value...
Looking at String.valueOf(Object)
, we see that it returns
if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
So, long story short, System.out.println(someObject)
calls that object's toString()
function to convert the object to a string representation.
If your object defines its own toString()
function, then that is what will be called. If you don't provide such a function, then your object will inherit toString()
from one of its parent classes. In the worst case, it will inherit Object.toString()
. That version of toString() is defined to return
a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object.
Or, in other words:
getClass().getName() + '@' + Integer.toHexString(hashCode())
So, when you call System.out.println()
on an object that doesn't define its own version of toString(), you might get the Object
version which looks like "classname@someHexNumber".
Why does this Java code implicitly calls toString() method?
System.out
is a PrintStream
instance that is a static member of System
. The PrintStream
class has a function println()
that accepts an argument of type Object
. That function, in Open JDK, looks like the following:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
And if you look at String.valueOf()
, which accepts an argument of type Object
, you can see:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
There is no magic. It's just a Java class that calls toString
on objects.
Further Reading
- Take a look at the docs for the PrintStream class: https://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html
Why System.out.println(new String(copyTo))?
There is no need for new String(copyTo)
there. copyTo
would suffice.
In general, you don't want to invoke println
on an array. For example:
System.out.println(new int[]{1, 2, 3});
wouldn't print [1, 2, 3]
or 123
, but rather something like [I@243432
. This is because there is no special overload for int[]
(or other array types, except for char[]
), so println(Object)
is used. This invokes toString()
on the parameter; but arrays don't have useful toString()
implementations.
However, the PrintStream.println(char[])
method does work somewhat sensibly, and produces an output as if the char[]
were converted to a String
first (but note that the toString()
method isn't used to produce this: no String
is created from the array).
System.out.println(new String(copyTo));
System.out.println(copyTo);
Output:
caffein
caffein
I suspect it's just an oversight/bug in the documentation that new String
is used. I filed a bug report with Oracle to get it fixed.
How does System.out.print() work?
System.out
is just an instance of PrintStream
. You can check its JavaDoc. Its variability is based on method overloading (multiple methods with the same name, but with different parameters).
This print stream is sending its output to so called standard output.
In your question you mention a technique called variadic functions (or varargs). Unfortunately that is not supported by PrintStream#print
, so you must be mistaking this with something else. However it is very easy to implement these in Java. Just check the documentation.
And if you are curious how Java knows how to concatenate non-string variables "foo" + 1 + true + myObj
, it is mainly responsibility of a Java compiler.
When there is no variable involved in the concatenation, the compiler simply concatenates the string. When there is a variable involved, the concatenation is translated into StringBuilder#append
chain. There is no concatenation instruction in the resulting byte code; i.e. the +
operator (when talking about string concatenation) is resolved during the compilation.
All types in Java can be converted to string (int
via methods in Integer
class, boolean
via methods in Boolean
class, objects via their own #toString
, ...). You can check StringBuilder's source code if you are interested.
UPDATE: I was curious myself and checked (using javap) what my example System.out.println("foo" + 1 + true + myObj)
compiles into. The result:
System.out.println(new StringBuilder("foo1true").append(myObj).toString());
How to use the toString method in Java?
From the Object.toString
docs:
Returns a string representation of the
object. In general, thetoString
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.The
toString
method for classObject
returns a string consisting of the
name of the class of which the object
is an instance, the at-sign character
`@', and the unsigned hexadecimal
representation of the hash code of the
object. In other words, this method
returns a string equal to the value
of:
getClass().getName() + '@' + Integer.toHexString(hashCode())
Example:
String[] mystr ={"a","b","c"};
System.out.println("mystr.toString: " + mystr.toString());
output:- mystr.toString: [Ljava.lang.String;@13aaa14a
Difference between printStackTrace() and toString()
No, there is an important difference! Using toString, you only have the type of the exception and the error message. Using printStackTrace() you get the whole stacktrace of an exception, which is very helpful for debugging.
Example of System.out.println(toString()):
java.io.FileNotFoundException: yourFile.txt (The system cannot find the file specified)
Example of printStackTrace():
java.io.FileNotFoundException: yourFile.txt (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:106)
at java.io.FileReader.(FileReader.java:55)
at ReadFromFile.main(ReadFromFile.java:14)
To make a string of the whole stacktrace, I usually use this method:
public static String exceptionStacktraceToString(Exception e)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
e.printStackTrace(ps);
ps.close();
return baos.toString();
}
Also note that simply calling toString()
simply returns a string, and won't print anything out.
toString() method within System.out.println() a double call?
No, it is not more efficient -- precisely because of the overload that you mentioned. Moreover, a call of toString
on a String
is extremely quick, so even without an overload the difference would not be measurable.
However, your professor is right about not making the call like System.out.println(object.toString());
, but the reason is different: since the call is unnecessary, the readers of your code may get confused.
I want to print an array with a toString() method in java, but without brackets and commas (so, not with Arrays.toString())
Change array.toString()
to toString(array)
. Also your method needs to be static
because main method is static. And if you want to use it in print statement, then it should return something. That's why I have changed the return type of your method to String
:
public static String toString(int[] num) {
String s = "";
for (int index = 0; index < num.length; index++) {
s += num[index];
}
return s;
}
public static void main(String[] args) {
//test negative number, output should be -10000000
int largeNum1[] = {-2, 0, 0, 0, 0, 0, 0, 0};
int largeNum2[] = {1, 0, 0, 0, 0, 0, 0, 0};
int numSize1 = (largeNum1.length + largeNum2.length) + 1;
int[] sum1 = new int[numSize1];
int[] answer1 = sumNumbers(largeNum1, largeNum2, sum1);
System.out.println((toString(largeNum1)) + " + " + (toString(largeNum2)) + " = " + (toString(answer1)));
}
How do I read / convert an InputStream into a String in Java?
A nice way to do this is using Apache commons IOUtils
to copy the InputStream
into a StringWriter
... something like
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();
or even
// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding);
Alternatively, you could use ByteArrayOutputStream
if you don't want to mix your Streams and Writers
Related Topics
Finding the Second Highest Number in Array
Randomly Select an Item from a List
Providing Input/Subcommands to Command Executed Over Ssh with Jsch
Can a Constructor in Java Be Private
How to Read JSON File into Java with Simple JSON Library
How to Redirect to Login Page When Session Is Expired in Java Web Application
Parsing JSON in Java Without Knowing JSON Format
Java Comparator Class to Sort Arrays
Does Java Have Built in Libraries for Audio _Synthesis_
Adding Image to Jbutton with Foreground Label
Why There Is No Concurrenthashset Against Concurrenthashmap
How Do Java Interfaces Simulate Multiple Inheritance
Why Is Class.Newinstance() "Evil"
How to Multiply Strings in Java to Repeat Sequences
Deserializing Polymorphic Types with Jackson Based on the Presence of a Unique Property
How to Convert Hex String to Java String
Eclipse: Attach Source/Javadoc to a Library via a Local Property