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?
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) { ...
To prevent the ClassCastException exception, one should be careful when casting objects to a specific class or interface and ensure that the target type is a child of the source type, and that the actual object is an instance of that type.
ClassCastException is a runtime exception raised in Java when we try to improperly cast a class from one type to another. It's thrown to indicate that the code has attempted to cast an object to a related class, but of which it is not an instance.
ClassCastException is one of the unchecked exception in Java. It can occur in our program when we tried to convert an object of one class type into an object of another class type.
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());
...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With