2009-10-22 3 views
5
public Configuration(Node node, File file) { 
    HashMap<String, String> conf = (HashMap<String, String>) SerializationUtils.deserialize(new FileInputStream(file)); 
} 

ich verstehen, warum dies eine unsichere Guss Warnung gibt, aber was ist die beste/akzeptierte Art und Weise dies sicher zu tun? Gibt es einen guten Weg?Unsafe generic Guss wenn Deserialisieren eine Sammlung

Antwort

2

Sie können diese Situation nicht vollständig typsicher handhaben, wenn Sie nur die Java-Sprache verwenden.

Da dies etwas ist, das immer wieder getan werden muss, und man kann wirklich nicht drum herum kommen, schlage ich vor, eine genreic Methode auf und generische Objekte zu lesen und werfen:

@SuppressWarnings("unchecked") 
public static <T> T readObject(
    ObjectInputStream in 
) throws IOException, ClassNotFoundException { 
    return (T)in.readObject(); 
} 

jedoch schlage ich vor, dass Sie solche Methoden normalerweise nicht verwenden, um gültige Warnungen zu unterdrücken.

+0

Das war, was ich hatte Angst; hatte nur gehofft, dass ich etwas verpasst habe:/ –

+0

Es ist eine gültige Warnung nur im Zusammenhang mit einem gebrochenen Sprachen-Feature-Design! –

+1

Wenn es keine Typlöschung gäbe, könnten wir diese Objekte nicht deserialisieren. Ich denke, es ist ein Sieg. –

2

Es gibt nicht wirklich eine Möglichkeit, diese richtig, weil die Informationen Kompilierung-Typ tun Sie (dh String) überprüfen wollen, ist zur Laufzeit nicht verfügbar ist, (das heißt, wenn die Besetzung tatsächlich auftritt) durch den Prozess als Löschung bekannt . Ich denke, dass der beste Weg ist, damit Sie Ihre entserialisierten Sammlung durch einig maßgeschneiderten „Checker“ zu übergeben:

Map<?,?> conf = deserialize(rsrc); 
Map<String, String> checked = checkMap(conf, String.class, String.class); 
//can use checked freely 

wo:

@SuppressWarnings("unchecked") 
public static <K, V> Map<K,V> checkMap(Map<?,?> map, Class<? extends K> k, Class<? extends V> v) { 
    for (Map.Entry<?, ?> e : map) { 
     k.cast(e.getKey()); //will throw ClassCastException 
     v.cast(e.getValue()); 
    } 
    return (Map<K,V>) map; //unchecked 
} 
+0

Wer möchte klären, warum eine vollkommen gültige und korrekte Antwort abgelehnt wurde? Liegt es daran, dass * I * zufällig eine ungültige und falsche Antwort abgelehnt hat? –

+0

Ich war nicht der Downvoter, aber ich kann sehen, dass dies im Fall von, sagen wir mal, Multithread-Zugriff nicht funktioniert. Ein Thread führt den Prüfer aus, während ein anderer den ursprünglichen Verweis verwendet, um den "falschen" Typ nach der Überprüfung einzufügen. Boom, ClassCastException. –

+0

@Steven - Ich glaube nicht * "könnte in einer Multithread-Umgebung unsicher sein" * ist notwendigerweise ein Fehler bei diesem "Check" -Ansatz. Ich habe meiner Antwort ein bisschen mehr Details hinzugefügt. Das Verfahren ist einfach nicht so ausgelegt, dass es auf diese Weise funktioniert und könnte somit für Gegengewicht –

1

auf der früheren Antwort zu bauen, gehe ich in der Regel ein wenig weiter wenn Warnungen unterdrückt werden. Ich habe die Annotation auf eine lokale Variable anstatt auf die Methode gesetzt, um den Umfang der Unterdrückung zu reduzieren. Dies bedeutet, dass wenn jemand mitkommt, die Methode später erweitert wird, wird es keine unbeabsichtigte Unterdrückung geben. Es fügt eine weitere Codezeile hinzu, aber ich denke, der Trade ist es wert.

Leider können Sie einem Ausdruck keine Anmerkung hinzufügen (zumindest noch nicht).

+0

Ich tendiere dazu, die Annotation auf die Methode zu setzen, weil der ganze Sinn der Methode darin besteht, eine Warnung zu unterdrücken. –