2008-10-09 5 views
6

Ich versuche, eine ClassCastException beim Deserialisieren eines Objekts aus XML abzufangen.Wie kann ich ClassCastException abfangen?

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

Und doch wird dies nicht als die Ausnahme nicht verfängt. Was würdest du vorschlagen?

+0

Retagged nutzen können häufige Ausnahme-releated-Tags zu verwenden. –

Antwort

8

Der Code in der Frage sollte Ihnen eine ungeprüfte Cast-Warnung geben. Hören Sie -Xlint.

Der gesamte Compiler weiß über T ist seine Grenzen, die es wahrscheinlich nicht (abgesehen von der expliziten Erweiterung von Object und einem Super vom Nulltyp) hat. So effektiv ist der Cast zur Laufzeit (Object) - nicht sehr sinnvoll.

Sie können eine Instanz der Klasse des parametrisierten Typs übergeben (vorausgesetzt, sie ist nicht generisch).

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

Oder als generische Methode:

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

Nun, ich kann nicht instanceof Operator als die Methode eine parametrisierte ist:

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

und Generika in Java sind kompilieren Zeit nur.

+0

Würde das nicht bedeuten, dass die Umwandlung in T tatsächlich vom Aufrufer ausgeführt wird, nicht von der Methode selbst? –

+0

Nicht sicher, ich verstehe Ihren Standpunkt. Als ein schneller Hack gebe ich ein Objekt von restore (..) zurück und führe eine instanceof check auf einer höheren Ebene durch, keine generischen involvierten (da sie sowieso nicht helfen). Trotzdem ist das hässlich. – yanchenko

3

Es wird jede Classcast nicht sein, es sei denn, Ihr T eine Basis hat:

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

Im obigen Beispiel wird es Keine ClassCastException in den ersten 5 Aufrufen von Cast und CastBaseNumber. Nur der 6. Aufruf löst eine ClassCastException aus, da der Compiler das cast() so umsetzt, dass er (Object) o zurückgibt, und castBaseNumber(), um (Number) o; zurückzugeben. If Sie schreiben

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

Sie würden eine Classcast bekommen, aber nicht whithin der guss Methode, aber bei der Zuordnung zu s.

Ich glaube daher, Ihre "T" ist nicht nur "T", sondern "T erweitert Something". So könnte man überprüfen:

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

Aber das führt immer noch zu einem Fehler später, wenn Sie Ihre Klasse verwenden.

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

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

Für diesen Fall könnte nur Toms Ratschlag helfen.

0

Wenn Sie nicht instaceof verwenden, können Sie möglicherweise die IsAssignableFrom Methode auf Klasse

Verwandte Themen