Как поймать ClassCastException?
Я пытаюсь поймать ClassCastException при десериализации объекта из xml.
и
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.
}
и все же это не будет, так как исключение не будет поймано. Что бы вы предложили?
4 ответов
код в вопросе должен дать вам непроверенное предупреждение о приведении. Слушать -Xlint.
все, что компилятор знает о T, - это его границы, которых он, вероятно, не имеет (кроме явно расширяющегося объекта и супер типа null). Так что эффективно приведение во время выполнения (Object) - не очень полезно.
что вы можете сделать, это передать экземпляр класса параметризованного типа (предполагая, что он не является универсальным).
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) {
...
}
}
}
или как универсальный метод:
public <T> T restore(Class<T> clazz, String from) {
...
try {
restoredItem = clazz.cast(decoder.readObject());
...
не будет никакого ClassCastException, за исключением случаев, когда ваш T имеет некоторую базу:
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;
}
}
в приведенном выше примере не будет ClassCastException в первых 5 вызовах cast и castBaseNumber. Только 6-й вызов вызывает ClassCastException, потому что компилятор эффективно переводит cast () для возврата (Object) o и castBaseNumber () для возврата (Number) o;. Если вы пишите
String s = GenericsTest.<Long> cast("Hallo");
вы получите ClassCastException, но не whithin cast-метод, но при назначении на s.
поэтому я думаю, что ваше " Т "- это не просто" т", но"т что-то расширяет". Так что вы можете проверить:
Object o = decoder.readObject();
if (o instanceof Something)
restoredItem = (T) o;
else
// Error handling
но это все равно приведет к ошибке позже, когда вы используете свой класс.
public Reader<T extends Number>{...}
Long l = new Reader<Long>("file.xml").getValue(); // there might be the ClassCastException
в этом случае может помочь только Совет Тома.
Ну, я не могу использовать instanceof
оператор, поскольку метод является параметризованным:
public T restore(String from){
...
restoredItem = (T) decoder.readObject();
...
}
и дженерики в Java являются только временем компиляции.