比较 EL 内的枚举值失败
Comparing enum value inside EL fails
我正在尝试比较 EL 中 JSP 页面中的 enum
。这应该支持 EL 3.0 版——我正在使用——及更高版本。这是我使用的代码和配置文件:
index.jsp:
<%@page import="net.myapp.MyClass" %>
<%@page import="net.myapp.MyClass.NestedEnum" %>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@page isELIgnored="false" %> <%-- default --%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
MyClass mc = new MyClass();
MyClass.NestedEnum[] enums = new MyClass.NestedEnum[]
{MyClass.NestedEnum.NE_VALUE_A, MyClass.NestedEnum.NE_VALUE_B};
request.setAttribute("enums", enums);
%>
<html>
<body>
<h2>Enums in EL</h2>
<c:forEach var="evalue" items="${enums}">
<c:choose>
<c:when test="${evalue == NE_VALUE_A}">
Value is NE_VALUE_A.
</c:when>
<c:when test="${evalue == NestedEnum.NE_VALUE_A}">
Value is NestedEnum.NE_VALUE_A.
</c:when>
<%-- This causes: javax.el.PropertyNotFoundException: No public static field named [NestedEnum] was found on (exported for Java 9+) class [net.myapp.MyClass]
<c:when test="${evalue == MyClass.NestedEnum.NE_VALUE_A}">
Value is MyClass.NestedEnum.NE_VALUE_A.
</c:when>
--%>
<c:otherwise>
Not value NE_VALUE_A. Actual value: ${evalue}
</c:otherwise>
</c:choose>
<br/>
</c:forEach>
</body>
</html>
MyClass.java:
package net.myapp;
public class MyClass {
private final NestedEnum value = NestedEnum.NE_VALUE_A;
public static enum NestedEnum {
NE_VALUE_A, NE_VALUE_B
}
public NestedEnum getValue() {
return value;
}
}
web.xml:
<web-app id="my-webapp" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
</web-app>
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- <dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>-->
</dependencies>
<build>
<finalName>my-webapp</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
when
块中的比较总是失败,我得到了 otherwise
块的输出。如果我使用字符串比较,例如
<c:when test="${evalue == 'NE_VALUE_A'}">
那么比较成功。但是,我想知道为什么与枚举值的比较失败。
PS:
该应用程序部署在 tomcat 服务器上,版本 9.0.31。 OS 使用 Java 11.
最简单的方法是将它与字符串进行比较:
<c:when test="${evalue == 'NE_VALUE_A'}">
这是因为 EL 的类型强制规则。
the EL specification 的第 1.8.2 节说以下强制规则适用于相等比较:
If A or B is an enum coerce both A and B to enum, apply operator
第 1.18.6 节说明了强制转换为枚举类型“T”的规则:
If A is a String call Enum.valueOf(T.getClass(), A) and return the result.
支持您一直尝试使用的语法,但事实证明无法使用 <%page import="…" %>
指令成功导入嵌套的 class 名称。这可能是因为真正的 class 名称类似于 net.myapp.MyClass$NestedEnum
.
不知道能不能把那个名字传给<%page import
指令。我从来没有尝试过。
(而且我一直想知道为什么常规 Java 编译器允许在常规 import
语句中嵌套 class 名称而没有单词 static
;我可以'在 Java 语言规范中找不到对它的支持。)
如果您将枚举类型设置为 top-level class,您的 EL 测试应该有效。
我正在尝试比较 EL 中 JSP 页面中的 enum
。这应该支持 EL 3.0 版——我正在使用——及更高版本。这是我使用的代码和配置文件:
index.jsp:
<%@page import="net.myapp.MyClass" %>
<%@page import="net.myapp.MyClass.NestedEnum" %>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@page isELIgnored="false" %> <%-- default --%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
MyClass mc = new MyClass();
MyClass.NestedEnum[] enums = new MyClass.NestedEnum[]
{MyClass.NestedEnum.NE_VALUE_A, MyClass.NestedEnum.NE_VALUE_B};
request.setAttribute("enums", enums);
%>
<html>
<body>
<h2>Enums in EL</h2>
<c:forEach var="evalue" items="${enums}">
<c:choose>
<c:when test="${evalue == NE_VALUE_A}">
Value is NE_VALUE_A.
</c:when>
<c:when test="${evalue == NestedEnum.NE_VALUE_A}">
Value is NestedEnum.NE_VALUE_A.
</c:when>
<%-- This causes: javax.el.PropertyNotFoundException: No public static field named [NestedEnum] was found on (exported for Java 9+) class [net.myapp.MyClass]
<c:when test="${evalue == MyClass.NestedEnum.NE_VALUE_A}">
Value is MyClass.NestedEnum.NE_VALUE_A.
</c:when>
--%>
<c:otherwise>
Not value NE_VALUE_A. Actual value: ${evalue}
</c:otherwise>
</c:choose>
<br/>
</c:forEach>
</body>
</html>
MyClass.java:
package net.myapp;
public class MyClass {
private final NestedEnum value = NestedEnum.NE_VALUE_A;
public static enum NestedEnum {
NE_VALUE_A, NE_VALUE_B
}
public NestedEnum getValue() {
return value;
}
}
web.xml:
<web-app id="my-webapp" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
</web-app>
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- <dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>-->
</dependencies>
<build>
<finalName>my-webapp</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
when
块中的比较总是失败,我得到了 otherwise
块的输出。如果我使用字符串比较,例如
<c:when test="${evalue == 'NE_VALUE_A'}">
那么比较成功。但是,我想知道为什么与枚举值的比较失败。
PS: 该应用程序部署在 tomcat 服务器上,版本 9.0.31。 OS 使用 Java 11.
最简单的方法是将它与字符串进行比较:
<c:when test="${evalue == 'NE_VALUE_A'}">
这是因为 EL 的类型强制规则。
the EL specification 的第 1.8.2 节说以下强制规则适用于相等比较:
If A or B is an enum coerce both A and B to enum, apply operator
第 1.18.6 节说明了强制转换为枚举类型“T”的规则:
If A is a String call Enum.valueOf(T.getClass(), A) and return the result.
支持您一直尝试使用的语法,但事实证明无法使用 <%page import="…" %>
指令成功导入嵌套的 class 名称。这可能是因为真正的 class 名称类似于 net.myapp.MyClass$NestedEnum
.
不知道能不能把那个名字传给<%page import
指令。我从来没有尝试过。
(而且我一直想知道为什么常规 Java 编译器允许在常规 import
语句中嵌套 class 名称而没有单词 static
;我可以'在 Java 语言规范中找不到对它的支持。)
如果您将枚举类型设置为 top-level class,您的 EL 测试应该有效。