2008-10-09 15 views
6

Estoy tratando de atrapar una ClassCastException al deserializar un objeto de xml.¿Cómo atrapo ClassCastException?

Así,

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. 
} 

Y, sin embargo esto no como la excepción no se quedan atrapados. ¿Qué sugieres?

+0

reetiquetado de usar etiquetas más comunes de excepción-releated. –

Respuesta

8

El código en la pregunta debería darle una advertencia de lanzamiento desactivada. Escucha a -Xlint.

Todo lo que el compilador conoce acerca de T es sus límites, que probablemente no tenga (aparte de extender Objeto explícitamente y un super del tipo nulo). Así que efectivamente el lanzamiento en tiempo de ejecución es (Objeto) - no muy útil.

Lo que puede hacer es pasar en una instancia de la Clase del tipo parametrizado (suponiendo que no sea genérico).

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) { 
      ... 
     } 
    } 
} 

o como un método genérico:

public <T> T restore(Class<T> clazz, String from) { 
     ... 
     try { 
      restoredItem = clazz.cast(decoder.readObject()); 
      ... 
0

Bueno, no puedo usar instanceof operador como el método es un parametrizada uno:

public T restore(String from){ 
... 
restoredItem = (T) decoder.readObject(); 
... 
} 

Y genéricos en Java son en tiempo de compilación solamente.

+0

¿No sugeriría eso que el reparto a T en realidad lo hace la persona que llama, no el método en sí? –

+0

No estoy seguro de que entienda bien su punto. Como hackeo rápido, devuelvo un Object from restore (...) y realizo una instancia de verificación en un nivel superior, sin genéricos involucrados (ya que de todos modos no ayudan). Aún así, esto es feo. – yanchenko

3

No habrá ninguna ClassCastException, excepto cuando su T tiene alguna 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; 
    } 
} 

En el ejemplo anterior, habrá no ClassCastException en las primeras 5 llamadas a cast y castBaseNumber. Solo la sexta llamada arroja una ClassCastException, porque el compilador traduce efectivamente el molde() para devolver (Objeto) o y el castBaseNumber() para devolver (Número) o ;. Cuando entra escribir

String s = GenericsTest.<Long> cast("Hallo"); 

Se podría conseguir un ClassCastException, pero no whithin el fundido método, pero a la asignación a s.

Por lo tanto, creo que su "T" no es solo "T", sino que "T extends Something". Así se puede comprobar:

Object o = decoder.readObject(); 
if (o instanceof Something) 
    restoredItem = (T) o; 
else 
    // Error handling 

Pero esto todavía va a conducir a un error más tarde, cuando el que utiliza su clase.

public Reader<T extends Number>{...} 

Long l = new Reader<Long>("file.xml").getValue(); // there might be the ClassCastException 

En este caso, solo los consejos de Tom pueden ser útiles.

0

Si no puede utilizar instaceof es posible que pueda utilizar el método isAssignableFrom en Clase

Cuestiones relacionadas