Java Generics - gemischte Objektkarten

8

Ich gewöhne mich immer noch an Java Generics, aber ich bin gerade dabei, eine Anwendung zu aktualisieren, die vor Generics geschrieben wurde, um die neueste Version von Java zu verwenden.

Problem ist, dass der Code nicht mit Typsicherheit geschrieben wurde!

Wir haben eine ganze Reihe von Maps, die grundsätzlich verschiedene Objekttypen einschließlich Strings enthalten. Zum Beispiel:

%Vor%

Jetzt kämpfe ich immer noch mit dem besten Weg, damit umzugehen, ohne eine ganze Menge Code umzuformen. Refactoring ist derzeit keine Option.

Momentan kann ich nichts mehr sehen, obwohl Map<String, Object> funktioniert, aber ich denke, es ist im Wesentlichen das Gleiche?

    
Dangerous Hamster 19.05.2017, 13:42
quelle

6 Antworten

10
  

Ich kämpfe immer noch mit dem besten Weg, damit umzugehen, ohne zu bekommen   Refactoring einer ganzen Menge Code

Also ändere sie überhaupt nicht. Die Rohtypen, also die nicht -generischen Typen, sind technisch immer noch gültig. Es ist nicht ideal und es wird eine Compilerwarnung generiert, aber der Code wird funktionieren (nun, so gut wie es jemals funktioniert hat).

Alle Klassen erweitern Object , sodass Sie einen beliebigen Wert in die folgende Map einfügen können:

%Vor%

Sie erhalten eine zusätzliche Garantie, dass der Schlüssel eine Zeichenkette ist, also etwas besser als die Verwendung des Rohtyps.

Grundsätzlich sollten Sie jedoch versuchen, die Verwendung einer Map zu vermeiden, wenn Sie den Typ des Schlüssels oder den Wert nicht definieren können.

    
Michael 19.05.2017, 13:50
quelle
2

Ab sofort können Sie nur den Rohtyp Map durch Map<String, Object> ersetzen; aber diese Art von Informationen ist nahe "nutzlos". Wenn Sie Ihre gesamte Komponente nicht auf die Verwendung von verschiedenen Kartenobjekten umstellen, können Sie nicht viel tun. Natürlich können Sie die Typwarnungen loswerden, aber Sie müssen instanceof jedes Mal überprüfen, wenn Sie auf einen Map-Wert zugreifen.

Als Ausweg: Wenn man annimmt, dass die Anzahl der "value" -Typen bekannt und einigermaßen klein ist, könnten Sie eine Reihe von Hilfsmethoden erstellen, die wie folgt aussehen:

%Vor%

Diese Methode könnte einen "Wrapper" um die allValues -Karte implementieren, der nur die Karteneinträge bereitstellt, die tatsächlich Date-Objekte sind.

Bedeutung: Sie behalten Ihr aktuelles Kartenobjekt, aber Sie stellen auf dieser Karte "spezialisiertere" Ansichten bereit. Dadurch können Sie einen neuen Code schreiben, der die zusätzlichen Typinformationen ausnutzt.

Aber natürlich ist das nicht kostenlos. Es fügt eine gewisse Komplexität hinzu und das Definieren der genauen Details solcher "Ansichtskarten" könnte sich als ziemlich kompliziert erweisen.

    
GhostCat 19.05.2017 13:50
quelle
2

Es gibt wenig, was Sie tun können, um die vollständige Überprüfung des statischen Typs zu erreichen, die bei richtig verwendeten Generika verfügbar ist. Ich glaube jedoch nicht, dass Sie die Typprüfung komplett aufgeben müssen und sich in diesem Fall auf das Casting in Echtzeit verlassen. Ich denke, du kannst einen Schritt dazu machen.

Ich nehme an, das ist eine allgemeine Karte, die der Code für allgemeine Speicherung benutzt, vielleicht für Persistenz oder Eigenschaften usw. Wenn das der Fall ist, können Sie wenigstens etwas in der Art tun:

%Vor%

Dies ist eine Art von Map -Halter, die dann die Map als korrektes generisches Objekt mit den korrekten Grenzen liefern kann. Hoffentlich werden Sie feststellen, dass bestimmte Module die gemeinsame Karte ausschließlich für Date s und andere String s verwenden. In Bereichen wie diesen können Sie Map<X,Y> as(...) verwenden, um Ihnen eine korrekt statisch geprüfte Karte für dieses Modul / Abschnitt zu geben und diese ausschließlich in diesem Codeabschnitt zu verwenden.

    
OldCurmudgeon 19.05.2017 14:29
quelle
2

Wie Michael vorgeschlagen hat Map<String, Object> map = new HashMap<>(); ist ein erster Schritt.
Es wird jedoch davon ausgegangen, dass Sie nur String als Schlüssel haben und Sie wahrscheinlich Objekte aus der Karte werfen müssen.

Ich denke, dass ein zweiter Schritt darin bestehen würde, diese Karte in mehrere Karten aufzuteilen, die einen spezifischeren Typ deklarieren:

%Vor%     
davidxxx 19.05.2017 13:49
quelle
1

Verwenden Sie keine Rohtypen ... siehe dies um zu wissen, warum ..

Nun können Sie es wie folgt ausbrechen, damit Sie es bekommen können:

Ihr map<K,V> hat als Schlüssel nur Strings, also ist K = string korrekt, andererseits scheinen "String1", new Date () und neue Custom Class nichts gemeinsam zu haben, sondern warten alle Klassen in Java erben tatsächlich die Object-Klasse ... das heißt, Sie können V = Object

tun

Jetzt kann Ihre Karte als Map<String, Object> und all dies

deklariert werden %Vor%

ist in Ordnung

    
quelle
1

Die Konvertierung von Nicht-Generika (z. B. altes Java) zu Generika kann eine echte PITA sein. Der einfachste Weg, dies zu tun, besteht darin, jede Map, Set, Liste durch verwandte generische, z.

%Vor%

aber nur, wenn gemappte Objekte auch keine Generika sind (oder Generika, die gerade zum Lesen verwendet werden). Z.B. wenn in deinem Code etwas wie

war %Vor%

Wenn Sie in solchen Fällen einen Karten-Getter finden und im Original-Code einen Put haben, werden Sie viele Probleme haben:

%Vor%

In diesem Fall können Sie keinen klaren Code haben: Wenn Sie Fragezeichen verwenden, treten Fehler auf, wie in

%Vor%

Sie haben also zwei Alternativen: Code neu schreiben (um Warnungen zu vermeiden) oder alles unter Objekte erzwingen und unkontrollierte Umwandlungen Warnungen erhalten.

%Vor%

Weitere Details zu Fragezeichen und Generika finden Sie hier: Was ist der Unterschied zwischen? und Objekt in Java-Generics?

    
Sampisa 19.05.2017 14:35
quelle

Tags und Links