jsf - List<T> 上的 UISelectMany 导致 java.lang.ClassCastException : java. lang.String 无法转换为 T

标签 jsf jsf-2 primefaces classcastexception selectmanycheckbox

我正在使用 <p:selectCheckboxMenu> List<Long>上:

<p:selectCheckboxMenu value="#{bean.selectedItems}">
    <f:selectItems value="#{bean.availableItems}" />
</p:selectCheckboxMenu>
private List<Long> selectedItems;
private Map<String, Long> availableItems;

提交表单并循环遍历所选项目时,如下所示,

for (int i = 0; i < selectedItems.size(); i++) {
    Long id = selectedItems.get(i);
    // ...
}

然后我得到一个类转换异常:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
    at com.example.Bean.submit(Bean.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:278)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    ... 27 more

<p:selectManyCheckbox> 也出现同样的问题, <p:selectManyMenu> , <h:selectManyMenu>等等。基本上都是多选组件。它在 <p:selectOneMenu> 中工作正常以及单个值上的所有其他单选组件 Long属性。

这是怎么造成的,如何解决?

最佳答案

您的问题是由以下事实引起的:

  1. Java 泛型是编译时语法糖,在运行时完全不存在。
  2. EL 表达式在运行时运行,而不是在编译时运行。
  3. HTTP 请求参数为 obtainedString

逻辑结果是:EL 看不到任何泛型类型信息。 EL 没有看到 List<Long> ,但是 List 。因此,当您没有显式指定转换器时,EL 在获取提交的值后将返回 StringList 中将其设置为未修改通过 reflection方法。当您尝试将其强制转换为 Long 时之后在运行时,您显然会面临 ClassCastException .

解决方案很简单:显式指定 String 的转换器至Long 。您可以使用 JSF 内置 LongConverter 其转换器 ID javax.faces.Long 。其他内置转换器列出 here .

<p:selectCheckboxMenu ... converter="javax.faces.Long">

无需显式指定转换器的另一种解决方案是更改 List<T>输入 T[] 。这样 EL 将看到 Long类型化数组,从而执行自动转换。但这可能需要对模型的其他地方进行更改,这可能是不可取的。

private Long[] selectedItems;

如果您使用复杂对象(javabean、实体、POJO 等)作为选择项值,而不是像 Long 这样的标准类型对于 JSF 有内置转换器的情况,同样的规则也适用。您只需要创建一个自定义Converter并在输入组件的 converter 中显式指定它属性,或依赖forClass如果你可以使用T[]Conversion Error setting value for 'null Converter' 中详细阐述了如何创建这样的转换器。 .

关于jsf - List<T> 上的 UISelectMany 导致 java.lang.ClassCastException : java. lang.String 无法转换为 T,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19872633/

相关文章:

java - 通过外部安排的 SSO 实现接缝安全

jsf - 如何在EL中通过#{component.id}获取列ID?

primefaces - 如何设置pe的文字颜色 :timer?

jsf - 在 Primefaces 4 中显示格式化的十进制数

javascript - Primefaces 水印 : hide placeholder on click

jsf - JSF 中的消息包

jakarta-ee - 在 JSF @ViewScoped 和 WebSocket @ServerEndpoint 之间共享数据

jsf-2 - @Produces 为JSF2 和JAX-RS 中的当前用户对象?

jsf-2 - java.lang.IllegalStateException : getOutputStream() has already been called for this response when calling JasperReport

ajax - Primefaces:所有ajax请求的默认oncomplete方法