Win a copy of Learn Spring Security (video course) this week in the Spring forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Please explain me this!

 
Sonam Arya
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you please tell me why this program is throwing ClassCastExcep


import java.util.*;
public class Car {
public int wheels = 0;
public Car(){}
public Car(int wheels) {
this.wheels = wheels;
}

public String toString() {
return new Integer(wheels).toString();
}
public static void main(String[] args) {
Car c1 = new Car(1);
Car c2 = new Car(2);
Car c3 = new Car(3);
TreeSet list = new TreeSet();
list.add(c3);
list.add(c1);
list.add(c2);
Iterator it = list.iterator();
while (it.hasNext())
System.out.print (it.next() + " ");
}
}
 
Bear Bibeault
Author and ninkuma
Marshal
Pie
Posts: 64613
86
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
"ScreenSunCert Desire", please check your private messages for an important administrative matter.
 
Henry Wong
author
Marshal
Pie
Posts: 20880
75
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you please tell me why this program is throwing ClassCastExcep


A TreeSet either requires you to use a Comparator, or have Comparable objects in the set. Since you are *not* using a Comparator, it is assuming that the objects are Comparable. Since your objects are not, this will generate a class cast exception.

Henry
 
Sonam Arya
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But if i implement comparator why does it print 1 2 3 since i added in 3 1 2 fashion, it should have printed in the same fashion

import java.util.*;
public class Car implements Comparator {
public int wheels = 0;
public Car(){}
public Car(int wheels) {
this.wheels = wheels;
}
public int compare(Object o1, Object o2) {
Car c1 = (Car)o1;
Car c2 = (Car)o2;
return new Integer(c1.wheels).compareTo(new Integer(c2.wheels));
}
public String toString() {
return new Integer(wheels).toString();
}
public static void main(String[] args) {
Car c1 = new Car(1);
Car c2 = new Car(2);
Car c3 = new Car(3);
TreeSet list = new TreeSet(new Car());
list.add(c3);
list.add(c1);
list.add(c2);
Iterator it = list.iterator();
while (it.hasNext())
System.out.print (it.next() + " ");
}
}
 
Henry Wong
author
Marshal
Pie
Posts: 20880
75
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But if i implement comparator why does it print 1 2 3 since i added in 3 1 2 fashion, it should have printed in the same fashion


A TreeSet sorts the set. And the sorted order is determined by the comparator (or comparables). You comparator does not sort by insertion order -- nor am I sure if it is possible to write one.

If you want insertion order, you might want to consider using the LinkedHashSet instead.

Henry
 
marc weber
Sheriff
Posts: 11343
Java Mac Safari
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you checked the API documentation?

In a TreeSet, "elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used." A TreeSet's iterator is "over the elements in this set in ascending order."
 
Manju Kavi
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
TreeSet is a sorted collection of elements. In order to put elements(objects) in set, the objects should be mutually comparable. And TreeSet uses Comparable(natural order) or Comparator(user defined) to sort the elements. Objects that we are trying to put in the sets should implement Comparable or Comparator and override compareTo() method. So while inserting objects, TreeSet makes use of this method to compare inserting element with each element in the set. Here is the updated program..
import java.util.*;
public class Car implements Comparable
{
public int wheels = 0;
public Car(){}
public Car(int wheels)
{
this.wheels = wheels;
}

public String toString()
{
return new Integer(wheels).toString();
}

public int compareTo(Object o)
{
Car c=(Car)o;
if(c.wheels>this.wheels)
return -1;
else if(c.wheels<this.wheels)
return 1;
else
return 0;

}

public static void main(String[] args)
{
Car c1 = new Car(1);
Car c2 = new Car(2);
Car c3 = new Car(3);
TreeSet list = new TreeSet();
list.add(c3);
list.add(c1);
list.add(c2);
Iterator it = list.iterator();
while (it.hasNext())
System.out.print (it.next() + " ");
}

}
 
Nabila Mohammad
Ranch Hand
Posts: 664
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aren't you supposed to use Casting with Iterator..?
i was pretty sure it would result in a Class Cast Exception

Then why didn't it cause any exception.

I thought ..only when you specify what type it is , then you dont require the casting ie
Iterator<Car> i= list.Iterator()
 
Ankit Garg
Sheriff
Posts: 9509
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, a cast is not needed for backward compatibility....
 
Nabila Mohammad
Ranch Hand
Posts: 664
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you please elaborate a little ..please!
 
Ankit Garg
Sheriff
Posts: 9509
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is no need to say please man, anything for you guys...

suppose there is a class that was compiled with jdk1.4, it takes a untyped ArrayList as parameter in one of it's methods,

void method(ArrayList al)
{
::
}

now if you want to pass a typed ArrayList to this method, then what? you might say that we will call it as

ArrayList<String> al = ...;
method((ArrayList)al);

but the compiler can't disallow you to call it directly, as the code might actually work without the cast. This is because after type erasure, there is no difference between a typed array list and un-typed list. So the compiler allows this with a unchecked warning...
 
Manju Kavi
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Nabila,
Yes you are right that we need a cast because iterator always returns element of type "Object". But here you never get that exception because we are not trying to assign the elements returned by the it.next() method to Car variable. Something like this..

while (it.hasNext())
{
Car c=it.next();
System.out.print (c+"");
}
In this case we get an error telling incompatible types.
Again when you use generics, casting is not necessary.
 
Manju Kavi
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here we are directly trying to display the elements returned by next() method. I think you know that when we try to display the object, then its toString() method is called. So here we are actually calling the toString() mothod of "Object" class which is overridden in the Car(subclass). Polymorphism!
 
Ankit Garg
Sheriff
Posts: 9509
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oops! I told a completely different thing
 
Nabila Mohammad
Ranch Hand
Posts: 664
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Manju - Thanks alot..

That means if the toString() method is overridden, then even if dont cast it's ok and it will run.

But if you dont overrider it ,then casting is necessary - and in if casting is not done, then it would give ClassCastException and not a compile time error.

Right???

Correct me if i am wrong.

I have my exam in like 2 hrs and this was really bothering me...
So just logged in to make sure
 
Nabila Mohammad
Ranch Hand
Posts: 664
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Manju:
Here we are directly trying to display the elements returned by next() method. I think you know that when we try to display the object, then its toString() method is called. So here we are actually calling the toString() mothod of "Object" class which is overridden in the Car(subclass). Polymorphism!



When you saidd displaying the object - it means using System.out.println() Right ...or something else..?
 
mukki pandey
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A TreeSet either requires you to use a Comparator, or have Comparable objects in the set. Since you are *not* using a Comparator, it is assuming that the objects are Comparable. Since your objects are not, this will generate a class cast exception.



Comparable objects in the sense.....i mean whats wrong with baove code

list.add(c1); this is calling construtor with interger values

can anyone please explain
 
Nabila Mohammad
Ranch Hand
Posts: 664
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by mukki pandey:
A TreeSet either requires you to use a Comparator, or have Comparable objects in the set. Since you are *not* using a Comparator, it is assuming that the objects are Comparable. Since your objects are not, this will generate a class cast exception.



Comparable objects in the sense.....i mean whats wrong with baove code

list.add(c1); this is calling construtor with interger values

can anyone please explain


Comparable means - you can compare them some how..
Like STring you can sorit it out in Alphabetical order
Number are sorted out in ascending order.

But in this case it does not know how sort the objects you are adding.
Because you havent specified any way .
And this specification is supposed to be give by implementing Comparator.
 
Rekha Srinath
Ranch Hand
Posts: 178
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nabila,

That means if the toString() method is overridden, then even if dont cast it's ok and it will run


Its not that if toString() is overridden, cast is not required. If you are going to assign the iterated value to some object, then the corresponding cast is required.

Say, for eg,
Animal a = (Animal) it.next(); // Cast required, because you are assigning it.next()'s return to an Animal reference

Object b = it.next (); // Cast not required, because it.next() returns an Object.

If we are just printing the iterated object contents using System.out.println, it means that we are using Object's toString() method and it has nothing to do with the casting that we are talking about here.
 
Nabila Mohammad
Ranch Hand
Posts: 664
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ohh ok..

i got the difference ..

Thanks.
 
Manju Kavi
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nabila,
Rekha is absolutely right, toString() is no where related to casting. Sorry i counldn't reply you before time.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic