在 JSP 中使用 JSTL <c:forEach> 遍歷 List<String>,並在 <c:when test="${looper eq pageHelper.pageNo}"> 比較時,若 pageNo 為 Long 型別,Tomcat 6.0.36 / 7.0.30 會拋出:
javax.el.ELException: Cannot convert ... of type class java.lang.String to class java.lang.Long
pageNo 為 Long,決定將後續比較的 looper 也轉為 Long。looper 為 "..."(分頁省略號)時,無法轉型為 Long,導致異常。String 比較,不會出錯。<c:forEach var="looper" items="${pageHelper.pageList}">
<c:choose>
<c:when test="${looper eq pageHelper.pageDot}">...</c:when>
<c:when test="${looper eq pageHelper.pageNo}">當前頁</c:when>
<c:otherwise>${looper}</c:otherwise>
</c:choose>
</c:forEach>
使用 JSTL fn:trim 或 fn:toString 將比較右邊轉為字串:
<%@ taglib prefix="fn" uri="https://java.sun.com/jsp/jstl/functions" %>
...
<c:when test="${looper eq fn:trim(pageHelper.pageNo)}">當前頁</c:when>
<c:when test="${looper eq fn:trim(pageHelper.pageDot)}">...</c:when>
pageNo 轉為 String 再放入 Model。eqStr 函數統一走字串比較邏輯。// 測試用例
List<String> list = Arrays.asList("1", "...", "3", "4");
Long pageNo = 3L;
String pageDot = "...";
for (String s : list) {
// 錯誤寫法:s == pageNo 會觸發 EL 轉型邏輯
// 正確寫法:
if (s.equals(pageDot)) { ... }
else if (s.equals(String.valueOf(pageNo))) { ... }
}
此為 Tomcat EL 實作缺陷,核心在於類型推斷順序導致非預期轉型。開發時應遵循「比較雙方型別一致」原則,或在 EL 中顯式轉型,避免依賴容器隱式轉換行為。