Frage Wie man List in die Liste umsetzt


Dies wird nicht kompiliert, kein Vorschlag geschätzt.

 ...
  List<Object> list = getList();
  return (List<Customer>) list;

Compiler sagt: kann nicht casten List<Object> zu List<Customer>


75
2017-12-16 21:23


Ursprung


Antworten:


Sie können jedes Objekt immer auf einen beliebigen Typ anwenden, indem Sie es zuerst in Object umwandeln. in Ihrem Fall:

(List<Customer>)(Object)list; 

Sie müssen sicherstellen, dass die Liste zur Laufzeit nur die Objekte des Kunden enthält.

Kritiker sagen, dass ein solches Casting anzeigt, dass etwas mit deinem Code nicht stimmt. Sie sollten Ihre Typdeklarationen optimieren können, um dies zu vermeiden. Aber Java-Generika sind zu kompliziert und nicht perfekt. Manchmal wissen Sie einfach nicht, ob es eine schöne Lösung gibt, um den Compiler zu erfüllen, obwohl Sie die Laufzeittypen sehr gut kennen und Sie wissen, was Sie zu tun versuchen, ist sicher. In diesem Fall, tun Sie einfach das Rohgießen nach Bedarf, so können Sie die Arbeit für zu Hause verlassen.


111
2017-12-17 10:42



Das ist, obwohl ein Kunde ist ein Objekt, eine Liste von Kunden ist kein Liste der Objekte Wenn es war, dann könntest du es tun irgendein Objekt in einer Liste von Kunden.


34
2017-12-16 21:25



Abhängig von Ihrem anderen Code kann die beste Antwort variieren. Versuchen:

List<? extends Object> list = getList();
return (List<Customer>) list;

oder

List list = getList();
return (List<Customer>) list;

Aber denken Sie daran, dass solche unkontrollierten Casts nicht empfohlen werden.


28
2017-12-16 21:28



Sie können eine Doppelbesetzung verwenden.

return (List<Customer>) (List) getList();

19
2017-12-18 18:18



Mit Java 8 Streams:

Manchmal ist Brute-Force-Casting in Ordnung:

List<MyClass> mythings = (List<MyClass>) (Object) objects

Aber hier ist eine vielseitige Lösung:

List<Object> objects = Arrays.asList("String1", "String2");

List<String> strings = list.stream()
                       .map(element->(String) element)
                       .collect(Collectors.toList());

Es gibt eine Menge Vorteile, aber eine davon ist, dass Sie Ihre Liste eleganter gestalten können, wenn Sie nicht sicher sein können, was darin enthalten ist:

list.stream()
    .filter(element->element instanceof String)
    .map(element->(String)element)
    .collect(Collectors.toList());

11
2017-07-19 19:27



Beachten Sie, dass ich kein Java-Programmierer bin, aber in .NET und C # wird diese Funktion Contravarianz oder Kovarianz genannt. Ich habe mich noch nicht mit diesen Dingen beschäftigt, da sie neu in .NET 4.0 sind, das ich nicht benutze, da es nur Beta ist, also weiß ich nicht, welcher der beiden Begriffe dein Problem beschreibt, aber lass mich das beschreiben technisches Problem damit.

Nehmen wir an, du könntest spielen. Beachten Sie, sage ich Besetzungweil du das gesagt hast, aber es gibt zwei mögliche Operationen, Gießen und konvertieren.

Konvertieren würde bedeuten, dass Sie ein neues Listenobjekt erhalten, aber Sie sagen Casting, was bedeutet, dass Sie ein Objekt vorübergehend als einen anderen Typ behandeln wollen.

Hier ist das Problem damit.

Was würde passieren, wenn das Folgende erlaubt wäre (ich nehme an, dass die Liste der Objekte vor der Besetzung nur Kundenobjekte enthält, sonst würde die Besetzung selbst in dieser hypothetischen Version von Java nicht funktionieren):

List<Object> list = getList();
List<Customer> customers = (List<Customer>)list;
list.Insert(0, new someOtherObjectNotACustomer());
Customer c = customers[0];

In diesem Fall würde dies versuchen, ein Objekt, das kein Kunde ist, als einen Kunden zu behandeln, und Sie würden einen Laufzeitfehler an einer Stelle entweder innerhalb der Liste oder von der Zuweisung erhalten.

Generics sollen dir jedoch typensichere Datentypen, wie Sammlungen, geben, und da sie das Wort "garantiert" herumwerfen wollen, ist diese Art von Cast mit den folgenden Problemen nicht erlaubt.

In .NET 4.0 (ich weiß, Ihre Frage war über Java), wird dies erlaubt in einigen sehr spezifischen Fällen, wobei der Compiler garantieren kann, dass die von Ihnen durchgeführten Operationen sicher sind, aber im Allgemeinen ist diese Art von Cast nicht erlaubt. Das gleiche gilt für Java, obwohl ich mir nicht sicher bin, ob ich Co- und Kontravarianz in die Java-Sprache einführen möchte.

Hoffentlich kann jemand mit besseren Java-Kenntnissen als ich Ihnen die Einzelheiten für die Java-Zukunft oder Implementierung sagen.


8
2017-12-16 21:28



Sie sollten einfach über die Liste iterieren und alle Objekte nacheinander darstellen


3
2017-12-16 21:27



Das kannst du nicht List<Object> und List<Customer> sind nicht im selben Vererbungsbaum.

Sie könnten einen neuen Konstruktor zu Ihrem hinzufügen List<Customer> Klasse, die ein List<Object> und dann iteriere durch die Liste, die jedes wirft Object zu einem Customer und fügen Sie es Ihrer Sammlung hinzu. Beachten Sie, dass beim Aufruf des Aufrufers eine ungültige Cast-Ausnahme auftreten kann List<Object> enthält etwas, das kein a ist Customer.

Der Sinn von generischen Listen besteht darin, sie auf bestimmte Typen zu beschränken. Sie versuchen, eine Liste zu nehmen, die haben kann etwas darin (Bestellungen, Produkte, etc.) und pressen Sie es in eine Liste, die nur Kunden annehmen kann.


2
2017-12-16 21:36