Question

Je me demandais quel est le type de données de la variable de modèle si le retour est réglé sur un modèle. Je l'ai vu dans un code quelque part, mais je ne sais pas d'où vient il jette la valeur récupérée de la session.

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

Le code de cette extérieur est:

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

La ligne rencontre ClassCastException lors de la coulée à mon objet. Mais quand j'ajoute regarder session.getAttribute ( « abc »), il montre que le type est MyClassType. Toute aide serait appréciée.

Il semble que ce code spécial pour l'aide du modèle fait le retour de getFromSessionMap un type de variable et donc pas besoin d'un plâtre. Cela fonctionne sur tous les cas, mais tout d'un coup, il a échoué dans une partie du code.

Était-ce utile?

La solution

  

Il semble que ce code spécial pour l'utilisation   modèle fait le retour de   getFromSessionMap un type de variable et   donc pas besoin d'un casting.

Fondamentalement, il doit être transtypage quelque part entre obtenir le résultat de session.getAttribute(sessionKey) et l'affectation à MyClassType. Le langage Java (et la machine virtuelle Java) ne permettent pas un objet qui n'est pas une instance de MyClassType (ou un sous-type de celui-ci) à assigner à une variable MyClassType.

Peu importe la façon dont vous écrivez le code, transtypage doit se produire . Et puisque l'attribut (apparemment) n'est pas un MyClassType (ou sous-type), vous obtenez un ClassCastException.

La vraie question est pourquoi ne vous obtient une erreur de compilation? Et la réponse est la @SuppressWarnings("unchecked")! Si vous avez supprimé cet avertissement, vous obtenez un message d'erreur « de conversion de type dangereux » pour cette ligne:

return (T) session.getAttribute(sessionKey);

En vérité, Java ne peut pas faire un type à un casting de type générique (réel). Et c'est-ce que le message d'avertissement / d'erreur est là pour signaler. En fait, une fois que le code a été compilé, ce code

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

est en fait pas différent dans le sens de ceci:

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

Techniquement parlant ce que l'on appelle "l'effacement de type".

Alors, où est le type de vérification / typecast passe réellement? La réponse est dans cette ligne:

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

Même si vous ne l'avez pas écrit un typecast ici, le code généré par le compilateur Java ne transtypage avant d'attribuer la valeur à type. Il doit. Parce que dans la mesure où il sait, l'exemple, il est assignant pourrait être any type d'objet.

D'autres affiches ont suggéré d'ajouter un argument de classe à getFromSessionMap. En soi, cela ne absolument rien . Si vous remplacez également le corps de la méthode avec:

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

vous provoquerez la méthode de faire en fait un réel contrôle de type. Mais cette seule cause ClassCastException d'être jeté à un endroit différent. Et l'instruction d'affectation sera toujours faire un type caché !! cast

Autres conseils

Dans l'exemple de la question, le type de retour est T. Le type effacé sera Object comme implicitement, T extends Object. La distribution réelle est réalisée dans le bytecode de la méthode d'appel (vous pouvez utiliser javap -c pour voir que).

En général, vous devez garder le nombre d'objets « de haut niveau » dans les sessions aussi petites que possible. L'un des avantages de le faire, est il n'y a plus besoin de méthodes aki comme celles-ci.

  

Toute aide serait appréciée parce que mon code rencontre ClassCastException.

Si vous obtenez un ClassCastException, cela signifie que vous essayez de jeter quelque chose dans quelque chose, ce n'est pas, comme dans le code suivant:

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

Le ClassCastException doit avoir un message de détail instructif, comme "java.lang.String ne peut pas être jeté à java.util.Date".

Vous utilisez le type moulé dans le corps de la méthode ( (T) session.getAttribute (sessionKey) ).

Cela signifie que vous dites explicitement au compilateur « Je suis absolument sûr que l'objet retourné IS-A T et prêt à gérer l'erreur si elle n'est pas » .

Voici votre hypothèse sur le type d'attribut était incorrect et vous avez obtenu une erreur. Donc, tout est correct et l'exécution vous fournit déjà avec le type d'objet réel de l'attribut qui n'est pas IS-A MyClassType.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top