I am writing a simple shopping program and I save a master list of all the items that are possible to buy as a Set of Components "Set<Component>". Component implements Serializable and I have no problem saving the data off, however when I read it back in I am getting a warning when I cast the readObject back into a Set<Component>. Yes, it works... but I'd like to know the proper way to do this code so that I don't have a compiler warning. Here is a snippet of my code with comments and extra statements removed to save space.
The warning is on the line: "components = (Set<Component>)objectInputStream.readObject();"
The warning is: "Type Safety: The cast from Object to Set<Component> is actually checking against the erased type Set"
Any help is appreciated, thank you! [ November 24, 2008: Message edited by: Brian Legg ]
Even if the cast to Set succeeds, the compiler still cannot guarantee that it is a Set<Component>. During runtime the <Component> part no longer exists, and anything could be in the Set. The compiler no longer can ensure that all elements are Components. That's why there is a warning.
In an ideal world you should check the contents of the Set first before making that cast. That will be quite a performance hit though. If you're sure enough that the Set is indeed Set<Component> you can use @SuppressWarnings annotation.
Just for this I've created a utility method that a) will ensure that the cast will either succeed or throw a ClassCastException, and b) handle the warning for me:
Plus of course matching methods for List, Map and several other interfaces in the Collections Framework ;) And of course also the matching isXXX methods for testing first. [ November 24, 2008: Message edited by: Rob Prime ]
[Brian]: Ok, I was trying to get around using the @SuppressWarning annotation, I always figured anytime I was using that that I was just telling the compiler to let me be a bad programmer.
Heh, there is that danger. Sometimes there's just not a better option, however, so you bite the bullet and go ahead and use @SuppressWarnings. Usually I try to apply @SuppressWarnings to the smallest possible area, so that I don't disable any more warnings than I have to. Since it's possible to annotate local variable declarations, we can often eliminate method-wide @SuppressWarnings by introducing a local variable declaration to store the result of the operation that would generate a warning - e.g. replace
Then you can remove the @SuppressWarnings from the rest of the method:
[ November 24, 2008: Message edited by: Mike Simmons ]
Originally posted by Brian Legg: Ok, I was trying to get around using the @SuppressWarning annotation, I always figured anytime I was using that that I was just telling the compiler to let me be a bad programmer.
Usually that is true, but sometimes you just can't avoid it.
For instance, when cloning a generic object and you are using a covariant return type:
Or creating an array using a Class<T> object:
In both examples you just know that the cast is safe - the API guarantees it. But still the compiler doesn't trust you. In those cases there is nothing else but suppress the warning.
You should refrain from suppressing warnings for entire classes though. In fact, you should do it as little as possible. Out of the 383 source files in my main library, only 11 suppress any warnings. And at 3% that's still too high, but there's little I can do about those.
Thanks Rob, I also have another question directed at you on an older post!
Joined: Nov 07, 2008
Thanks Mike, I appreciate it!
I have another "warning" I will post in a new topic later. I think this one is more serious though and relates to a design flaw.