While looking up (testing) information for another question, I came across something and had completely no clue why it was happening. Now, I know that there is no practical
The crux of the question is:
And why is it fine for the println() method to call its toString, but not for me to directly?
ClassCastException exception isn't occurring due to calling toString() but due to an explicit cast added by the compiler.
A picture is worth thousand words, so let's look at some decompiled code.
Consider following code:
public static void main(String[] args) {
List s = new ArrayList();
s.add("kshitiz");
List i = new ArrayList(s);
System.out.println(i.get(0)); //This works
System.out.println(i.get(0).toString()); // This blows up!!!
}
Now look at the decompiled code:
public static void main(String[] args) {
ArrayList s = new ArrayList();
s.add("kshitiz");
ArrayList i = new ArrayList(s);
System.out.println(i.get(0));
System.out.println(((Integer)i.get(0)).toString());
}
See the explicit cast to Integer? Now why didn't compiler add a cast in previous line? The signature of the method println() is:
public void println(Object x)
Since println is expecting an Object and result of i.get(0) is Object no cast is added.
It is also okay for you to invoke toString(), granted that you do it like this so that no cast is generated:
public static void main(String[] args) {
List s = new ArrayList();
s.add("kshitiz");
List i = new ArrayList(s);
myprint(i.get(0));
}
public static void myprint(Object arg) {
System.out.println(arg.toString()); //Invoked toString but no exception
}