webentwicklung-frage-antwort-db.com.de

Warnung vor ungeprüfter Zuweisung

Ich verwende Android Studio 1.1.0.

Dies verursacht keine Warnung:

public static class A {
    public Map<Integer, String> getMap() {
        return null;
    }
}

public static class B {
    public void processA(A a) {
        Map<Integer, String> map = a.getMap();
    }
}

Aber mach A generisch:

public static class A<T> {
    public Map<Integer, String> getMap() {
        return null;
    }
}

Und diese Zeile:

Map<Integer, String> map = a.getMap();

bekommst du jetzt eine Warnung: "Unchecked assignment: 'Java.util.Map to Java.util.Map<Java.lang.Integer, Java.lang.String>'.

Obwohl die Signatur von getMap völlig unabhängig von T ist und der Code in Bezug auf die in Map enthaltenen Typen eindeutig ist.

Ich weiß, dass ich die Warnung beseitigen kann, indem ich processA wie folgt neu implementiere:

public <T> void processA(A<T> a) {
    Map<Integer, String> map = a.getMap();
}

Aber warum sollte ich das tun müssen? Was macht T hier überhaupt aus?

Die Frage ist also: Warum muss die Typlöschung nicht nur T betreffen (was verständlich ist - wenn ich eine Instanz von A übergebe, ist T ein Unbekannter ), sondern auch "hardcoded" generische Signatur wie <Integer, String> in diesem Fall?

26
Konrad Morawski

In Ihrem zweiten Fall, wenn Sie dies tun:

public void processA(A a)

Was meinst du mit A? Bedeutet das A<String> Oder A<List<String>> Oder was? Möglicherweise verwenden Sie nichts, was mit dem Typ A zu tun hat, aber der Compiler kennt diese Tatsache nicht. Für den Compiler ist nur A ein Zeichen von Panik.

In Ihrem Fall können Sie:

public void processA(A<?> a) {
    Map<Integer, String> map = a.getMap();
} 

Ein Argument vom Typ A<?> Bedeutet, dass Sie den Typ von A nicht besonders beachten und lediglich einen Platzhalter angeben. Für Sie bedeutet dies: Jedes Objekt von A mit einem beliebigen Typ, wie es sein generischer Typ tun würde. In Wirklichkeit bedeutet dies, dass Sie den Typ nicht kennen. Es ist nutzlos, weil Sie nichts in Bezug auf A auf typsichere Weise tun können, da ? Praktisch alles sein kann!

Aber gemäß Ihrem Methodenkörper ist es weltweit sinnvoll, A<?> Zu verwenden, da Sie an keiner Stelle im Körper tatsächlich den Typ A benötigen.

18
Jatin

Wenn Sie beabsichtigen, einen A<T> Eines beliebigen Typs T zu akzeptieren, aber den T nicht benötigen, wird dies korrekt ausgedrückt, indem Sie einen Platzhalter verwenden und A<?>. Wenn Sie dies tun, wird die Warnung in Ihrem Code entfernt:

public void processA(A<?> a) {
    Map<Integer, String> map = a.getMap();
}

Die Verwendung des bloßen Typs A wird nicht gleichwertig behandelt. Wie in Java Language Specification erläutert, sind solche Raw-Typen nicht für die Verwendung in neuem Code vorgesehen:

Die ungeprüfte Konvertierung wird verwendet, um eine reibungslose Interoperation von vor der Einführung generischer Typen geschriebenem Legacy-Code mit Bibliotheken zu ermöglichen, die einer Konvertierung zur Verwendung von Generizität unterzogen wurden (ein Prozess, den wir Generierung nennen). In solchen Fällen (insbesondere bei Clients des Collections Framework in Java.util) verwendet der Legacy-Code Basistypen (z. B. Collection anstelle von Collection <String>). Ausdrücke von Rohtypen werden als Argumente an Bibliotheksmethoden übergeben, die parametrisierte Versionen derselben Typen wie die Typen der entsprechenden formalen Parameter verwenden.

Solche Aufrufe können unter dem Typsystem mit Generika nicht als statisch sicher ausgewiesen werden. Das Zurückweisen solcher Aufrufe würde große Teile des vorhandenen Codes ungültig machen und verhindern, dass sie neuere Versionen der Bibliotheken verwenden. Dies wiederum würde Bibliotheksverkäufer davon abhalten, die Vorteile der Generizität zu nutzen. Um eine solche unerwünschte Wendung von Ereignissen zu verhindern, kann ein Rohtyp in einen willkürlichen Aufruf der generischen Typdeklaration konvertiert werden, auf die sich der Rohtyp bezieht. Die Umwandlung ist zwar nicht in Ordnung, wird jedoch als Zugeständnis an die Praktikabilität geduldet. In solchen Fällen wird eine ungeprüfte Warnung ausgegeben.

9
Dan Getz