TreeSet ts = new TreeSet(); ts.clear(); ts.add(0.1); ts.add(3.0); ts.add(100.0); ts.add(13.2); ts.add(5); //<----Throws ClassCastException System.out.println("The size of TreeSet is = " + ts.size()); itr = ts.iterator(); while(itr.hasNext()) System.out.println(itr.next());
In the code above, the line ts.add(5) throws ClassCastException at runtime. If I change it to a double value 5.0(i.e., Double object after autoboxing), then all is well. My understanding is that argument to the add method of TreeSet should be an object that implements Comparable interface. The TreeSet will try to cast the argument to Comparable and if the cast is illegal then it will throw ClassCastException.
So here the other elements of TreeSet are Double objects, I am trying to add an Integer object, however both are Comparable so the cast should atleast succeed, it may fail later on during comparison. I am not sure how the comparison using compareTo() will work here between Double and Integer objects. Is the Integer object being casted to Double object for comparison ? If yes, then that would surely throw ClassCastException....
[Rupak]: The TreeSet will try to cast the argument to Comparable and if the cast is illegal then it will throw ClassCastException.
Yes - but this isn't the only casting that gets done. After an object in TreeSet is cast to Comparable, the compareTo() method gets called. For most Comparable classes, the compareTo() method will throw a ClassCastException if the other object being compared to isn't a member of the same class. That isif Apple and Orange both implement Comparable, you still can't compare an Apple to an Orange. You can compare an Apple to an Apple, or an Orange to an Orange. But if you mix the two up, you will get a ClassCastException - that's what is happening here.
Is the Integer object being casted to Double object for comparison ? If yes, then that would surely throw ClassCastException....
As you've seen, this is one of the potential problems with autoboxing - the compiler may not autobox to the type you want it to. One solution is to make sure your numbers are all doubles, by writing 5.0 rather than 5 for example. It's easy tomake a mistake here though, as you've seen. I recommend taking advantage of another 5.0 feature, generics, to provide additional information to the compiler so it will be able to catch errors like this at compile time (rather than waiting for the ClassCastException at run time):
[Mark]: What I think the issue is it is trying to do a primitive conversion and an Auto-boxing at the same time, and the compiler can't do both
Right. In the original code it does the autoboxing to Integer, but no conversion because at compile time, there's no apparent need for a conversion. In my code, the compiler has enough information to tell that autoboxing without conversion is not enough, so it gives a compile-time error to force the programmer to fix the problem. [ July 12, 2005: Message edited by: Jim Yingst ]