JSTL Access Integer/Long key in Hash Map

2019-07-19 06:08发布

I am facing some problem in using EL in JSTL and not able to access Java Hash Map as I would like. I am aware that in EL the key, if Integer gets accessed as Long. I have following hash map definition that I am trying to access in JSTL -

Map<Long, Object> testMap = new HashMap<Long, Object>();

In JSP page, I need to check if the map contains a specific key or not. I attempt to do that by checking if not empty as following -

<c:if test='${ ! empty testMap[currObj.currVal]}'>

I also access the map's value for a key somewhere in the code like below -

<c:if test='${ testMapMap[5].data == 'something'}'>

Now the problem -

If i define my map above as <Integer, Object> then the first c:if works but second fails (as the second tries to access it as Long). However, if I define my map above as <Long, Object> the first if check always fails as it always recognizes it as empty but the second if statement where I check for the value works.

Is there any good way to make sure I access HashMap for both the if statements correctly? I will appreciate opinions.

1条回答
手持菜刀,她持情操
2楼-- · 2019-07-19 06:31

What is currObj? Can you redefine its currVal member as a Long (or long)?


A numeric literal (matching the IntegerLiteral production in the EL syntax) will be represented as a Long. The expression currObj.currVal evaluates to an Integer. A Long never equals() an Integer, so one expression must result in a different type.

Essentially, what you need is an explicit type conversion. Nothing like this is built into EL, but you could create a custom EL function to do it for you. This is a static function that you implement in Java, then describe in a TLD. Another answer of mine gives an example of the packaging. Here's what the function and its usage could look like in your case.

package com.y.taglib.core;

public final class CoercionUtil {

  public static Long toLong(Long n) {
    return n;
  }

}

The TLD would look like this:

<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">
  <tlib-version>1.0</tlib-version>
  <short-name>x-c</short-name>
  <uri>http://dev.y.com/taglib/core/1.0</uri>
  <function>
    <description>Coerce to a java.lang.Long.</description>
    <display-name>long</display-name>
    <name>long</name>
    <function-class>com.y.taglib.core.CoercionUtil</function-class>
    <function-signature>java.lang.Long toLong(java.lang.Long)</function-signature>
  </function>
</taglib>

In your JSP:

<%@taglib uri="http://dev.y.com/taglib/core/1.0" prefix="my" %>
...
<c:if test='${ ! empty testMap[my:long(currObj.currVal)]}'>

The JSP engine takes care of the necessary type coercion (from the Integer result of currVal to the Long required by the toLong() method. Your method is there simply to indicate the required type; without it, the JSP engine sees the (erased) type of the argument of testMap.get(Object), and doesn't see the need to perform any coercion since Integer is-an Object.

查看更多
登录 后发表回答