Frage

Ich frage mich, was ist der Datentyp des Template-Variable, wenn die Rückkehr zu einer Vorlage festgelegt ist. Ich habe dies in einem Code irgendwo gesehen, aber ich weiß nicht, wo hat es den Wert aus der Sitzung abgerufen werfen.

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

Der Code für diese außerhalb ist:

MyClassType type = request.getFromSessionMap("abc");

Die Linie Begegnungen Classcast wenn zu meinem Objekt Gießen. Aber wenn ich hinzufügen session.getAttribute ( „abc“) zu sehen, es zeigt, dass der Typ MyClassType ist. Jede mögliche Hilfe würde geschätzt.

Anscheinend spezieller Code für Vorlage macht die Rückkehr von getFromSessionMap einen Variablentyp und daher keine Notwendigkeit für eine Besetzung. Dies funktioniert auf alle Fälle aber plötzlich versagt es in einem Teil des Codes.

War es hilfreich?

Lösung

  

Anscheinend spezieller Code für die Verwendung von   Schablone macht die Rückkehr von   getFromSessionMap eine variable Art und   daher keine Notwendigkeit für eine Besetzung.

Im Grunde gibt hat ist eine Typumwandlung irgendwo zwischen dem Ergebnis session.getAttribute(sessionKey) bekommen und die Zuordnung zu MyClassType. Die Java-Sprache (und die JVM) wird nicht zulassen ein Objekt, das keine MyClassType Instanz (oder ein Subtyp davon) zu einer MyClassType Variablen zugewiesen werden.

Egal, wie Sie den Code schreiben, eine Typumwandlung hat auftreten. Und da das Attribut (scheinbar) keine MyClassType (oder Subtyp), Sie bekommen eine ClassCastException.

Die eigentliche Frage ist, warum Sie keinen Übersetzungsfehler zu bekommen? Und die Antwort ist der @SuppressWarnings("unchecked")! Wenn Sie diese Warnung entfernt, würden Sie eine „nicht sichere Typumwandlung“ Fehlermeldung für diese Linie erhalten:

return (T) session.getAttribute(sessionKey);

In Wahrheit Java kann eine (reale) Typumwandlung zu einer generischen Art nicht. Und das ist es, was die Warnung / Fehlermeldung gibt es darauf hinweisen. In der Tat, wenn der Code kompiliert wurde, dieser Code

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

ist eigentlich nicht anders aus, diese Bedeutung:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

Technisch gesehen ist dies "Typ Löschung" bezeichnet.

Also, wo ist die Typprüfung / Typumwandlung auftretende tatsächlich? Die Antwort ist in dieser Zeile:

MyClassType type = request.getFromSessionMap("abc");

Auch wenn Sie keine Typumwandlung hier geschrieben haben, erzeugt der Code durch den Java-Compiler hat eine Typumwandlung, bevor Sie den Wert auf type zuweisen. Es muss. Denn soweit er weiß, die Instanz könnte es zuweist sein jeder Objekttyp.

Andere Plakate haben ein Klasse-Argument Zugabe zu getFromSessionMap vorgeschlagen. Von selbst dies tut absolut nichts . Wenn Sie auch den Körper des Verfahrens ersetzen mit:

return clazz.cast(session.getAttribute(sessionKey));

Sie werden das Verfahren tatsächlich dazu führen, eine echte Typprüfung zu tun. Aber die einzige Ursache ClassCastException zu an einem anderen Ort geworfen werden. Und die Zuweisungsanweisung wird immer noch eine versteckte Art Guss tun !!

Andere Tipps

In dem Beispiel der Frage, der Rückgabetyp ist T. Der gelöschte Typ wird Object als implizit T extends Object sein. Die tatsächliche Besetzung wird in den Bytecode des anrufenden Verfahren durchgeführt (Sie javap -c das sehen können).

Im Allgemeinen sollten Sie die Anzahl der „Top-Level“ Objekte in Sessions so klein wie möglich halten. Einer der Vorteile, das zu tun, gibt es keine Notwendigkeit mehr für Hacky Methoden wie diese.

  

Jede Hilfe würde geschätzt, weil mein Code Classcast begegnet.

Wenn Sie eine ClassCastException bekommen, das bedeutet Sie Guss etwas in etwas sind versucht, es ist nicht, wie in den folgenden Code:

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

Die ClassCastException sollte eine erhellende Detail Nachricht haben, wie "java.lang.String kann nicht auf java.util.Date gegossen werden".

Sie verwenden Typumwandlung innerhalb der Methode Körper ( '(T) session.getAttribute (sessionKey) ).

Das bedeutet, dass Sie explizit zu Compiler sagen ‚Ich bin absolut sicher, dass zurückgegebene Objekt IST-A-T und bereit zum Griff Fehler, wenn dies nicht der Fall‘ .

Hier ist Ihre Annahme über Attributtyp war falsch und einen Fehler bekommen. Also, alles ist richtig und Laufzeit schon liefert Ihnen mit dem realen Attribut Objekttyp, der nicht ist IS-A MyClassType.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top