this error occurs when you try to cast an Object reference variable to some other type like this Set. Because of polymorphism a reference to Object could also be a reference to any other object because all classes implicitly are derived from Object. Therefore the compiler complains and you as a programmer have to confirm that you know what you're doing and confirm that the reference variable of type "Object" really contains a Set<Item>.
You could use the @SuppressWarnings("unchecked") annotation to suppress this warning but generally it's better to rethink your code which causes this unsafe cast. Perhaps there's a better way to solve this issue
Marco [ May 29, 2008: Message edited by: Marco Ehrentreich ]
Joined: Oct 26, 2007
Perhaps there's a better way to solve this issue
hi Marco Ehrentreich,
this is great that answer but above line does not make any head start to me
Let's try with an example. You probably have something like:
So, this is what I believe Marco meant: in your class A, the Set is declared to contain Object. So, any type of objects can be inserted there, it can be instances of Item or not.
In your class B, you would get the warning because you are expecting the set to contain only instances of Item. However there may be other types in it. The compiler has no way to check that, so it gives you the warning. It is up to the developer to make sure it works in run time.
of course I can try to explain in a little more detail. The basic problem with your code is the same as Rodrigo gave you with his example. As I already said it has to do with the concept of polymorphism. In fact this is a very fundamental concept of object oriented programming. So I think you don't have very much experience with object orientation?!? This is definitely something you'll have to learn if you want code in Java (or any other OO language).
I'll try to give you a short explanation on this. In Java all classes are implicitly inherited from Object (note the capital letter). So every class and object (no capital!) ranging from String to Set or to your own classes in Java is a child of Object.
The other thing are reference variables which "point" to an object of any specified class like
But because of polymorphism it's not only possible to assign objects of class Shape to this variable shape! It's also allowed to assign any object of any classes which are childre of Shape because they extend shape (inheritance). If you have children of Shape like class Rectangle or Circle it's absolutely legal to use the above variable as follows:
To come back to your problem, you have a reference variable of type Object (which was Shape in my example) and you want to downcast it to type Set<Item>. Because of polymorphism like I described above this variable isn't restricted to point to an object of type Object. No, it could even point to a String object, a List object, a Shape object, a House object or a Set<Item> object because this classes are all children of class Object.
And the point here is that even if you're sure that your reference variable of type Object is pointing to a Set<Item> the compiler doesn't know that!!! For the compiler this could be an object of type Object or any class type derived from Object. For this reason you explicitly have to tell the compiler that you really, really know that it's a variable of type Object but it points to a an object of type Set<Item> and it's safe to do the cast!
I hope now you understand the problem a little bit better. Unfortunately it's very hard to explain such topics in a few sentences here and of course I don't know how familiar you are with OOP. Just let me know if something is still unclear!
Why does the 3rd line throw the "Unchecked cast" warning and not the 2nd?
Why do I have to use @suppressWarning for the 3rd line and not the 2nd? Why, why, why?
That's because the reason for unchecked cast is not polymorphism as earlier indicated, but java's implementation of generics, i.e. the type parameters to classes such as List<String>.
For non-parameterized types, the actual type of each object is known to the vm. So if you do
The vm will know that o is actually a String and will be able to verify (during runtime) that you made a correct cast.
The thing is that the vm does not hold the actual type of the parameters for parametrized (generic) types during runtime - the information that the List is holding Strings is removed.
The vm knows only that it is a List, but does not know if it is List<String> or List<Integer>, so it cannot verify that you are making the correct cast, hence the warning:
Observe, that if you try to do:
It is the compiler, not the vm that will stop you. The compiler sees the full types of the variables and will prevent the program from being compiled due to illegal cast.