Réponse initiale (EL 2.1, mai 2009)
Comme mentionné dans ce fil de discussion du forum java :
Fondamentalement, l'autoboxing place un objet Integer dans la carte. c'est à dire:
map.put(new Integer(0), "myValue")
EL (Expressions Languages) évalue 0 comme un Long et cherche donc un Long comme clé dans la carte. c'est-à-dire qu'il évalue:
map.get(new Long(0))
Comme a Long
n'est jamais égal à un Integer
objet, il ne trouve pas l'entrée dans la carte.
C'est tout en un mot.
Mise à jour depuis mai 2009 (EL 2.2)
Décembre 2009 a vu l'introduction d'EL 2.2 avec JSP 2.2 / Java EE 6 , avec quelques différences par rapport à EL 2.1 .
Il semble (" EL Expression parsing integer as long ") que:
vous pouvez appeler la méthode intValue
sur l' Long
objet self dans EL 2.2 :
<c:out value="${map[(1).intValue()]}"/>
Cela pourrait être une bonne solution de contournement ici (également mentionné ci-dessous dans la réponse de Tobias Liefke )
Réponse originale:
EL utilise les wrappers suivants:
Terms Description Type
null null value. -
123 int value. java.lang.Long
123.00 real value. java.lang.Double
"string" ou 'string' string. java.lang.String
true or false boolean. java.lang.Boolean
Page JSP démontrant ceci:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page import="java.util.*" %>
<h2> Server Info</h2>
Server info = <%= application.getServerInfo() %> <br>
Servlet engine version = <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %><br>
Java version = <%= System.getProperty("java.vm.version") %><br>
<%
Map map = new LinkedHashMap();
map.put("2", "String(2)");
map.put(new Integer(2), "Integer(2)");
map.put(new Long(2), "Long(2)");
map.put(42, "AutoBoxedNumber");
pageContext.setAttribute("myMap", map);
Integer lifeInteger = new Integer(42);
Long lifeLong = new Long(42);
%>
<h3>Looking up map in JSTL - integer vs long </h3>
This page demonstrates how JSTL maps interact with different types used for keys in a map.
Specifically the issue relates to autoboxing by java using map.put(1, "MyValue") and attempting to display it as ${myMap[1]}
The map "myMap" consists of four entries with different keys: A String, an Integer, a Long and an entry put there by AutoBoxing Java 5 feature.
<table border="1">
<tr><th>Key</th><th>value</th><th>Key Class</th></tr>
<c:forEach var="entry" items="${myMap}" varStatus="status">
<tr>
<td>${entry.key}</td>
<td>${entry.value}</td>
<td>${entry.key.class}</td>
</tr>
</c:forEach>
</table>
<h4> Accessing the map</h4>
Evaluating: ${"${myMap['2']}"} = <c:out value="${myMap['2']}"/><br>
Evaluating: ${"${myMap[2]}"} = <c:out value="${myMap[2]}"/><br>
Evaluating: ${"${myMap[42]}"} = <c:out value="${myMap[42]}"/><br>
<p>
As you can see, the EL Expression for the literal number retrieves the value against the java.lang.Long entry in the map.
Attempting to access the entry created by autoboxing fails because a Long is never equal to an Integer
<p>
lifeInteger = <%= lifeInteger %><br/>
lifeLong = <%= lifeLong %><br/>
lifeInteger.equals(lifeLong) : <%= lifeInteger.equals(lifeLong) %> <br>
Un autre conseil utile en plus du commentaire ci-dessus serait lorsque vous avez une valeur de chaîne contenue dans une variable telle qu'un paramètre de requête. Dans ce cas, le passage de ceci entraînera également la saisie par JSTL de la valeur de disons "1" comme une piqûre et, en tant que telle, aucune correspondance ne sera trouvée dans un hashmap de carte.
Une façon de contourner ce problème est de faire quelque chose comme ça.
<c:set var="longKey" value="${param.selectedIndex + 0}"/>
Celui-ci sera désormais traité comme un objet Long et aura ensuite une chance de correspondre à un objet lorsqu'il est contenu dans la carte Map ou autre.
Ensuite, continuez comme d'habitude avec quelque chose comme
la source
Vous pouvez utiliser toutes les fonctions de Long, si vous mettez le nombre dans "(" ")". De cette façon, vous pouvez convertir le long en un entier:
<c:out value="${map[(1).intValue()]}"/>
la source
Sur la base du post ci-dessus, j'ai essayé ceci et cela a bien fonctionné, je voulais utiliser la valeur de la carte B comme clés pour la carte A:
<c:if test="${not empty activityCodeMap and not empty activityDescMap}"> <c:forEach var="valueMap" items="${auditMap}"> <tr> <td class="activity_white"><c:out value="${activityCodeMap[valueMap.value.activityCode]}"/></td> <td class="activity_white"><c:out value="${activityDescMap[valueMap.value.activityDescCode]}"/></td> <td class="activity_white">${valueMap.value.dateTime}</td> </tr> </c:forEach> </c:if>
la source
Si vous venez tout juste d'avoir
Map
avec lesInteger
clés que vous ne pouvez pas changer, vous pouvez écrire une fonction EL personnalisé pour convertir unLong
àInteger
. Cela vous permettrait de faire quelque chose comme:<c:out value="${map[myLib:longToInteger(1)]}"/>
la source