2013-06-08 8 views
8

ich Generika in Java, aber es ist nicht so gut, wie ich dachteSammlung sicherer als Standardliste mit generischem Typ?

public static void add(List l, Object o) { 
    l.add(o); 
} 

public static void main(String[] args) throws Exception { 
    List<Integer> list = new ArrayList<Integer>(); 
    add(list, "1.23"); 
    add(list, 1.23); 
    System.out.println(list); 
} 

diese kompiliert alle und arbeitet. Wenn ich einen Wert von list bekomme, wird eine Ausnahme ausgelöst.

Kann es in Java 6 sicherer sein?

+3

Warum gehst du nicht Verwenden Sie die 'list.add()' Methode? Deklarieren Sie Ihre 'add()' Methode mit dem generischen 'List ' Parameter. – NINCOMPOOP

+0

Ich verstehe, aber ich Gesicht Typ löschen (alter Code) –

+0

@KalamarObliwy: Aber es wird Sie von Kompilierzeit Fehler speichern und wird daher von 'ClassCastExceptions' zur Laufzeit speichern. – NINCOMPOOP

Antwort

14

Ich schlage vor, den Standard Collections mit:

List<Integer> checked = Collections.checkedList(list, Integer.class); 

dann arbeiten nur auf checked. Eine ClassCastException wird während der Einfügung einer nicht kompatiblen Instanz ausgelöst - früher (also besser) als zuvor (d. H. Während des Abrufs).

N.B. Überprüfen Sie Ihre Compiler-Nachrichten, ich würde wetten, dass Sie einige Warnungen gedruckt haben, die unsicheren/ungeprüften Code erwähnen. Ihr Problem ist genau das, was der Compiler Ihnen zu sagen versucht. Wenn Sie die Signatur von add kontrollieren, machen Sie es generisch - es gibt Ihnen Kompilierzeitsicherheit.

public static <T> void add(List<T> list, T t) { 
    list.add(t); 
} 
+0

+1 für den 'Collections.checkedList()' Vorschlag. 'Add()' sollte jedoch ermöglichen, dass Untertypen des deklarierten Typs eingefügt werden, so dass der Compiler, wenn die Liste als "Liste " deklariert wurde, alles hinzufügen würde. Daher wäre 'List ' besser geeignet als 'List '. –

+0

Wenn das OP plant, ** nur zur "Liste" hinzuzufügen **, dann hast du recht. Ich dachte allgemeiner. – emesx

+0

Eine 'add()' Methode sollte generell nur * zu einer Liste hinzufügen;) aber bei zweiten Gedanken glaube ich * ich lag falsch * :): da es sich um eine Sammlung und ein Element handelt, wird das Element "promoted" vom Compiler zum Super-Typ transparent. Was ich gesagt habe, gilt eigentlich nur für zwei generische Typen: 'A ' und 'B ', da diese invariant sind. –

3

Ich glaube nicht. Wenn diese statische add() Methode eine Tatsache des Lebens ist (etwas, das Sie nicht kontrollieren), können Sie nicht viel tun, weil Java Generics so implementiert werden, dass sie mit Java < 5.0 kompatibel sind.

Wenn Sie jedoch die Lage sind, die Unterschrift der add() Methode zu ändern, können Sie einfach die Typprüfung erzwingen, so dass Sie Compiler-Fehler für den Code in Ihrer main() Methode erhalten:

public static <T> void add(List<? super T> list, T object) { 
    list.add(object) 
} 
Verwandte Themen