Frage

In meiner Frühlingsanwendungskontextdatei habe ich so etwas wie:

<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
    <entry key="some_key" value="some value" />
    <entry key="some_key_2" value="some value" />   
</util:map>

In der Java -Klasse sieht die Implementierung aus wie:

private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

In Eclipse sehe ich eine Warnung, die sagt:

Geben Sie Sicherheit ein: Deaktiviert von Objekt zu HashMap.

Was habe ich falsch gemacht? Wie löste ich das Problem?

War es hilfreich?

Lösung

Nun, zuallererst verschwenden Sie das Gedächtnis mit dem neuen HashMap Schöpfungsanruf. Ihre zweite Zeile ignoriert den Verweis auf diese erstellte Hashmap vollständig und stellt den Müllsammler dann zur Verfügung. Also, tu das nicht, benutze:

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

Zweitens beschwert sich der Compiler darüber, dass Sie das Objekt an a übertragen HashMap ohne zu überprüfen, ob es a ist HashMap. Aber selbst wenn Sie tun würden:

if(getApplicationContext().getBean("someMap") instanceof HashMap) {
    private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}

Sie würden diese Warnung wahrscheinlich immer noch bekommen. Das Problem ist, getBean kehrt zurück Object, Es ist also nicht bekannt, was der Typ ist. Konvertieren in HashMap Direkt würde das Problem mit dem zweiten Fall nicht verursachen (und vielleicht würde es im ersten Fall keine Warnung geben, ich bin mir nicht sicher, wie pedantisch der Java -Compiler mit Warnungen für Java 5 ist). Sie konvertieren es jedoch in a HashMap<String, String>.

Hashmaps sind wirklich Karten, die ein Objekt als Schlüssel betrachten und ein Objekt als Wert haben. HashMap<Object, Object> wenn man so will. Daher gibt es keine Garantie dafür HashMap<String, String> Weil du hättest haben könntest HashMap<Date, Calendar> Weil die nicht generische Darstellung, die zurückgegeben wird, Objekte haben kann.

Wenn der Code kompiliert und Sie ausführen können String value = map.get("thisString"); Machen Sie sich ohne Fehler keine Sorgen um diese Warnung. Wenn die Karte jedoch nicht vollständig von String -Tasten zu Stringwerten ist, erhalten Sie eine ClassCastException Zur Laufzeit, da die Generika dies in diesem Fall nicht blockieren können.

Andere Tipps

Das Problem ist, dass eine Besetzung eine Laufzeitprüfung ist - aber aufgrund der Typ -Löschung gibt es zur Laufzeit tatsächlich keinen Unterschied zwischen a HashMap<String,String> und HashMap<Foo,Bar> für jeden anderen Foo und Bar.

Verwenden @SuppressWarnings("unchecked") und halte deine Nase. Oh, und Kampagne für refizierte Generika in Java :)

Wie die obigen Nachrichten angeben, kann die Liste nicht zwischen a unterschieden werden List<Object> und ein List<String> oder List<Integer>.

Ich habe diese Fehlermeldung für ein ähnliches Problem gelöst:

List<String> strList = (List<String>) someFunction();
String s = strList.get(0);

mit den folgenden:

List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);

Erläuterung: Der erste Typ Conversion überprüft, ob das Objekt eine Liste ist, ohne sich um die darin enthaltenen Typen zu kümmern (da wir die internen Typen auf der Listenebene nicht überprüfen können). Die zweite Konvertierung ist jetzt erforderlich, da der Compiler nur weiß, dass die Liste einige Objekte enthält. Dies überprüft den Typ jedes Objekts in der Liste, wie er zugegriffen wird.

Eine Warnung ist genau das. Eine Warnung. Manchmal sind Warnungen irrelevant, manchmal nicht. Sie sind es gewohnt, Ihre Aufmerksamkeit auf etwas zu lenken, von dem der Compiler glaubt, dass es ein Problem sein könnte, aber nicht.

Im Fall von Casts wird es in diesem Fall immer eine Warnung geben. Wenn Sie absolut sicher sind, dass eine bestimmte Besetzung sicher ist, sollten Sie kurz vor der Linie eine solche Annotation hinzufügen (ich bin mir nicht sicher):

@SuppressWarnings (value="unchecked")

Sie erhalten diese Nachricht, weil GetBean eine Objektreferenz zurückgibt und Sie sie auf den richtigen Typ werfen. Java 1.5 gibt Ihnen eine Warnung. Das ist die Natur, Java 1.5 oder besser mit Code zu verwenden, der so funktioniert. Spring hat die TypeSafe -Version

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");

Auf seiner Todo -Liste.

Wenn Sie die Warnungen wirklich loswerden möchten, können Sie eine Klasse erstellen, die sich aus der generischen Klasse erstreckt.

Zum Beispiel, wenn Sie versuchen zu verwenden

private Map<String, String> someMap = new HashMap<String, String>();

Sie können eine neue Klasse wie solche erstellen

public class StringMap extends HashMap<String, String>()
{
    // Override constructors
}

Dann, wenn Sie verwenden

someMap = (StringMap) getApplicationContext().getBean("someMap");

Der Compiler weiß, was die (nicht mehr generischen) Typen sind, und es wird keine Warnung geben. Dies ist möglicherweise nicht immer die perfekte Lösung, einige könnten diese Art von Niederlagen als Zweck generischer Klassen argumentieren, aber Sie verwenden immer noch den gleichen Code aus der generischen Klasse. Sie möchten verwenden.

Eine andere Lösung, wenn Sie das gleiche Objekt viel werfen und Ihren Code nicht verstreuen möchten @SupressWarnings("unchecked"), würde sein, eine Methode mit der Annotation zu erstellen. Auf diese Weise zentralisieren Sie die Besetzung und reduzieren hoffentlich die Fehlermöglichkeit.

@SuppressWarnings("unchecked")
public static List<String> getFooStrings(Map<String, List<String>> ctx) {
    return (List<String>) ctx.get("foos");
}

Der folgende Code führt zu einer Sicherheitswarnung vom Typ

Map<String, Object> myInput = (Map<String, Object>) myRequest.get();

Problemumgehung

Erstellen Sie ein neues Kartenobjekt, ohne die Parameter zu erwähnen, da der in der Liste gehaltene Objekttyp nicht überprüft wird.

Schritt 1: Erstellen Sie eine neue temporäre Karte

Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();

Schritt 2: Instantieren Sie die Hauptkarte

Map<String, Object> myInput=new HashMap<>(myInputObj.size());

Schritt 3: Iterieren Sie die temporäre Karte und stellen Sie die Werte in die Hauptkarte ein

 for(Map.Entry<?, ?> entry :myInputObj.entrySet()){
        myInput.put((String)entry.getKey(),entry.getValue()); 
    }

Die Lösung, um die ungeprüfte Warnung zu vermeiden:

class MyMap extends HashMap<String, String> {};
someMap = (MyMap)getApplicationContext().getBean("someMap");
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top