2009-09-30 3 views
17

Ich habe eine Liste, die garantiert nur ein Typ Objekt enthält. Dies wird durch einen zugrunde liegenden Code in einer Bibliothek verursacht, den ich nicht aktualisieren kann. Ich möchte eine Liste <ObjectType> basierend auf dem eingehenden List -Objekt erstellen, so dass mein aufrufender Code mit List <ObjectType> kommuniziert.Konvertieren von nicht generischen Listentyp in generische List Typ in Java 1.5

Wie konvertiert man die Liste (oder eine andere Objektgruppe) am besten in eine Liste <ObjectType>.

Antwort

13

Wenn mit Legacy-Code inter arbeitet, die einen Platzhalter nicht Typ Parameter für generische Typen angeben, verwenden. Beispiel: Angenommen, Sie eine Methode in einer älteren Bibliothek aufrufen, die einfach wieder ein rohes Collection:

Collection getItems(); 

In Ihrem Code, um das Ergebnis zu einer Variablen mit einem Platzhalter erklärt zuweisen:

Collection<?> items = widget.getItems(); 

Diese Auf diese Weise bewahren Sie die Typsicherheit, so dass Sie keine Warnungen erhalten.

Der Legacy-Code könnte (in einem Kommentar, höchstwahrscheinlich) angeben, was die generischen Parameter sein sollten. Zum Beispiel:

/** 
* @return the items, as a Collection of {@link Item} instances. 
*/ 
Collection getItems(); 

In diesem Fall haben Sie die Wahl. Sie können das Ergebnis zu einem Collection<Item> umwandeln, aber wenn Sie dies tun, verlassen Sie sich zu 100% auf die Third-Party-Bibliothek, und verwerfen die Versicherung von Java generischen Typen: dass jede zur Laufzeit ausgelöst ClassCastException direkt an einer expliziten auftritt Besetzung.

Was passiert, wenn Sie der Drittanbieterbibliothek nicht vollständig vertrauen, aber trotzdem eine Collection<Item> erstellen müssen? Erstellen Sie dann eine neue Sammlung, und fügen Sie den Inhalt hinzu, nachdem Sie sie in den erwarteten Typ umgewandelt haben. Auf diese Weise, wenn es einen Fehler in der Bibliothek gibt, erfährst du es sofort, anstatt einen Code weit weg zu haben und viel später auf mysteriöse Weise mit einer ClassCastException zu explodieren.

Zum Beispiel:

Collection<?> tmp = widget.getItems(); 
Collection<Item> items = new ArrayList<Item>(tmp.size()); 
for (Object o : tmp) 
    items.add((Item) o); /* Any type error will be discovered here! */ 

Für einen Fall, in dem der Typparameter nicht zur Compile-Zeit bekannt ist, können Sie die type-checked collection factories der Collections Klasse.

+0

Das Problem ist, dass Sie nicht wirklich etwas anderes als das Schweigen der Warnungen "Rohtyp" gewinnen. Die Umstellung auf Generika würde die Vorteile nutzen! –

+1

Welchen Nutzen haben Generika? Es soll Ihren Code nicht schön aussehen lassen und weniger Tipparbeit erfordern! Es ist dies: * Ihr Code ist garantiert typsicher, wenn er ohne Warnungen kompiliert wird. * Das ist es. Wenn Sie die Warnungen ignorieren oder unterdrücken, können Sie Generika überhaupt nicht verwenden, da Sie nur Situationen erstellen, in denen Code ohne einen Operator für die Umwandlung mysteriöserweise "ClassCastException" auslöst. – erickson

11

Sie können einfach die Liste werfen:

List raw = new ArrayList(); 
    List<String> generic = (List<String>) raw; 
+2

Wenn die Liste tatsächlich eine Art von Element enthält, ist dies eine gute Antwort. –

+1

Das ist ein großes "wenn". Es hängt sehr vom Kontext ab. – erickson

+0

Ich kann garantieren, dass die Liste den einen Elementtyp enthält. Dies war Code, der in Java 1.4-Vorgenerika geschrieben wurde. –

1

Die beste und sicherste Weg ist java.util.Collections Methode ‚checkedList (List Liste der Klasse-Typ)‘

Mit dieser Methode alle Elemente in Ihrer alten Liste verwenden wird bereits geprüft werden möglich.

+0

Funktioniert 'checkedList' in Java 5 nicht nur auf neue (und leere) generische Listen? Schlägst du vor, dass wir die nicht-generische 'checkedList' vor Java 5 benutzen? Dieses Legacy-Formular wird nicht in eine allgemeine Liste konvertiert. –

0

Wenn Sie nur an List<T> an irgendeinem alten Ort werfen, erhalten Sie eine "ungeprüfte" Compiler-Warnung. Wir haben das gelöst, indem wir es zu einer Utility-Methode verschoben haben.

public class Lists { 
    @SuppressWarnings({"unchecked"}) 
    public static <T> List<T> cast(List<?> list) { 
     return (List<T>) list; 
    } 
} 

Anrufer erhält jetzt keine Warnung, z.:

for (Element child : Lists.<Element>cast(parent.getChildren())) { 
    // ... 
} 

Das checkedList Dienstprogramm ist eine gute Idee in der Theorie, aber in der Praxis saugt es in der Klasse, die Sie erwarten passieren zu lassen. Ich hoffe, Java wird irgendwann generische Tippinformationen erhalten.

1

Versuchen Sie folgendes:

List<ObjectType> objectsWithType = Arrays.asList((ObjectType[])wildcardObjects).toArray()); 

Aber denken Sie daran, dass dies eine feste Länge Liste erzeugt. Wenn Sie versuchen, Elemente aus dieser Liste hinzuzufügen oder zu entfernen, wird ein Fehler ausgegeben. Seien Sie also immer vorsichtig, wenn Sie Arrays.asList() verwenden.

Verwandte Themen