2008-10-09 11 views
6

Próbuję złapać wyjątek ClassCastException podczas deserializacji obiektu z xml.Jak złapać wyjątek ClassCastException?

Więc

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

A jednak to nie jako wyjątek nie dać się złapać. Co byś zasugerował?

+0

Retagged użyć bardziej popularne tagi wyjątku releated. –

Odpowiedz

8

Kod w pytaniu powinien dać Ci niezaznaczone ostrzeżenie o obsadzie. Posłuchaj - Xlint.

Wszystkie kompilacje wiedzą o tym, że T to jego ograniczenia, których prawdopodobnie nie ma (oprócz wyraźnie rozszerzającego Object i super typu zerowego). Tak skutecznie rzutowanie w czasie wykonywania jest (Object) - niezbyt użyteczne.

Co można zrobić, to przekazać instancję klasy sparametryzowanego typu (zakładając, że nie jest generyczna).

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

Albo jako ogólny sposób:

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

Cóż, nie mogę używać instanceof operatora jako metoda jest sparametryzowanego jeden:

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

I rodzajowych w Javie są tylko w czasie kompilacji.

+0

Czy to nie sugerowałoby, że obsada T jest wykonywana przez osobę dzwoniącą, a nie przez samą metodę? –

+0

Nie jestem pewien, czy rozumiem. Jako szybki hack zwracam obiekt z przywracania (..) i wykonuję sprawdzenie instancji na wyższym poziomie, bez udziału generycznych (ponieważ i tak nie pomagają). Wciąż jest to brzydkie. – yanchenko

3

Nie będzie żadnych ClassCastException, z wyjątkiem, gdy T ma pewne podstawy:

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

w powyższym przykładzie, nie będzie brak wyjątku ClassCastException w pierwszych 5 wywołaniach Cast i CastBaseNumber. Tylko szóste połączenie rzuca wyjątek ClassCastException, ponieważ kompilator skutecznie tłumaczy metodę cast() na return (Object) o i castBaseNumber() na return (Number) o ;. Wenn piszesz

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

Można by dostać ClassCastException, ale nie w obrębie tej metody odlewania, ale na przypisanie do s.

Dlatego uważam, że twoje "T" to nie tylko "T", ale "T rozszerza coś". Więc można sprawdzić:

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

Ale to nadal będzie prowadzić do błędu później, gdy używasz klasę.

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

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

W tym przypadku może pomóc tylko radę Toma.

0

Jeśli nie można używać instaceof może być w stanie korzystać z metody isAssignableFrom na klasy

Powiązane problemy