Reputation: 57166
I'm trying to catch a ClassCastException when deserializing an object from xml.
So,
try {
restoredItem = (T) decoder.readObject();
} catch (ClassCastException e){
//don't need to crash at this point,
//just let the user know that a wrong file has been passed.
}
And yet this won't as the exception doesn't get caught. What would you suggest?
Upvotes: 12
Views: 38131
Reputation: 17307
If you can't use instaceof you might be able to use the isAssignableFrom method on Class
Upvotes: 0
Reputation: 3805
There will not be any ClassCastException, except when your T has some base:
public class GenericsTest
{
public static void main(String[] args)
{
System.out.println(cast(Integer.valueOf(0)));
System.out.println(GenericsTest.<Long> cast(Integer.valueOf(0)));
System.out.println(GenericsTest.<Long> cast("Hallo"));
System.out.println(castBaseNumber(Integer.valueOf(0)));
System.out.println(GenericsTest.<Long> castBaseNumber(Integer.valueOf(0)));
System.out.println(GenericsTest.<Long> castBaseNumber("Hallo"));
}
private static <T extends Number> T castBaseNumber(Object o)
{
T t = (T)o;
return t;
}
private static <T> T cast(Object o)
{
T t = (T)o;
return t;
}
}
In the above example, there will be no ClassCastException in the first 5 calls to cast and castBaseNumber. Only the 6th call throws a ClassCastException, because the compiler effectively translates the cast() to return (Object) o and the castBaseNumber() to return (Number)o;. Wenn you write
String s = GenericsTest.<Long> cast("Hallo");
You would get a ClassCastException, but not whithin the cast-method, but at the assignment to s.
Therefore I do think, your "T" is not just "T", but "T extends Something". So you could check:
Object o = decoder.readObject();
if (o instanceof Something)
restoredItem = (T) o;
else
// Error handling
But this will still lead to an error later, when the you use your class.
public Reader<T extends Number>{...}
Long l = new Reader<Long>("file.xml").getValue(); // there might be the ClassCastException
For this case only Tom's advise might help.
Upvotes: 3
Reputation: 147154
The code in the question should give you an unchecked cast warning. Listen to -Xlint.
All the compiler knows about T is its bounds, which it probably doesn't have (other than explicitly extending Object and a super of the null type). So effectively the cast at runtime is (Object) - not very useful.
What you can do is pass in an instance of the Class of the parameterised type (assuming it isn't generic).
class MyReader<T> {
private final Class<T> clazz;
MyReader(Class<T> clazz) {
if (clazz == null) {
throw new NullPointerException();
}
this.clazz = clazz;
}
public T restore(String from) {
...
try {
restoredItem = clazz.cast(decoder.readObject());
...
return restoredItem;
} catch (ClassCastException exc) {
...
}
}
}
Or as a generic method:
public <T> T restore(Class<T> clazz, String from) {
...
try {
restoredItem = clazz.cast(decoder.readObject());
...
Upvotes: 11
Reputation: 57166
Well, I can't use instanceof
operator as the method is a parametrized one:
public T restore(String from){
...
restoredItem = (T) decoder.readObject();
...
}
And generics in Java are compile-time only.
Upvotes: 0