You are actually calling
PrintStream.println(Object x)
instead of
public void println(String x)
The PrintStream.println(Object x)
implementation is below:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
The method calls String.valueOf(x)
whose implementation is below:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Note that the Object.toString()
method is being called.
Notes on implicit conversion
An Object
is only implicitly converted to a String
using the toString
method when the string concatenation operator (+
) is invoked. More exactly the conversion works as follows:
A value x of primitive type T is first converted to a reference value...
This reference value is then converted to type String by string conversion.
Now only reference values need to be considered.
If the reference is null, it is converted to the string "null" (four
ASCII characters n, u, l, l). Otherwise, the conversion is performed
as if by an invocation of the toString method of the referenced object
with no arguments; but if the result of invoking the toString method
is null, then the string "null" is used instead.
The toString method is defined by the primordial class Object"
Java Language Specification 15.18.1
One language (of many) that expand on the idea of implicit conversions is Scala which allows one to bring a conversion (e.g., A -> B) into scope which is then invoked whenever some type (A) is passed as an argument when a different type (B) is required.