列表< T>上的UISelectMany.导致java.lang.ClassCastException:java.lang.String无法转换为T [英] UISelectMany on a List<T> causes java.lang.ClassCastException: java.lang.String cannot be cast to T
问题描述
我在List<Long>
上使用 <p:selectCheckboxMenu>
:
I am using <p:selectCheckboxMenu>
on a List<Long>
:
<p:selectCheckboxMenu value="#{bean.selectedItems}">
<f:selectItems value="#{bean.availableItems}" />
</p:selectCheckboxMenu>
private List<Long> selectedItems;
private Map<String, Long> availableItems;
提交表单并按以下方式遍历所选项目时,
When submitting the form and looping over the selected items as below,
for (int i = 0; i < selectedItems.size(); i++) {
Long id = selectedItems.get(i);
// ...
}
然后我得到一个类强制转换异常:
Then I get a class cast exception:
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
属性上的所有其他单选组件中,它都可以正常工作.
The same problem occurs with <p:selectManyCheckbox>
, <p:selectManyMenu>
, <h:selectManyMenu>
, etc. All multiple-selection components basically. It works fine in <p:selectOneMenu>
and all other single-selection components on a single value Long
property.
这是怎么引起的,我该如何解决?
How is this caused and how can I solve it?
推荐答案
您的问题是由以下事实引起的:
Your problem is caused by the following facts:
- Java泛型是编译时的语法糖,在运行时完全不存在.
- EL表达式在运行时而非编译时运行.
- HTTP请求参数为逻辑结果是:EL没有看到任何通用类型信息. EL没有看到
List<Long>
,但是看到了List
.因此,当您未明确指定转换器时,EL将在获取提交的值作为String
后,通过List中将其设置为未修改的值. /reflect/"rel =" nofollow noreferrer>反射 表示.当您随后尝试在运行时将其强制转换为Long
时,显然会遇到ClassCastException
.Logical consequence is: EL doesn't see any generic type information. EL doesn't see a
List<Long>
, but aList
. So, when you don't explicitly specify a converter, EL will after obtaining the submitted value asString
set it unmodified in theList
by reflection means. When you attempt to cast it toLong
afterwards during runtime, you'll obviously face aClassCastException
.解决方案很简单:为
String
到Long
显式指定一个转换器.您可以使用内置的JSFLongConverter
具有转换器ID 此处列出了其他内置的转换器The solution is simple: explicitly specify a converter for
String
toLong
. You can use the JSF builtinLongConverter
for this which has the converter IDjavax.faces.Long
. Other builtin converters are listed here.<p:selectCheckboxMenu ... converter="javax.faces.Long">
另一种无需显式指定转换器的解决方案是将
List<T>
类型更改为T[]
.这样,EL将看到Long
类型的数组,从而执行自动转换.但这可能需要在模型中的其他位置进行更改,这可能是不希望的.Another solution without the need to explicitly specify the converter is to change
List<T>
type to aT[]
. This way the EL will see theLong
typed array and thus perform automatic conversion. But this possibly requires changes elsewhere in the model which may not be desirable.private Long[] selectedItems;
如果您使用复杂的对象(javabean,实体,POJO等)作为选择项值,而不是使用JSF内置转换器的标准类型(如
Long
),则同样的规则也适用.您只需要创建一个自定义Converter
并在输入组件的converter
属性中显式指定它,或者如果可以使用T[]
则依赖于forClass
. 转换错误设置中详细说明了如何创建此类转换器.空转换器的值.In case you're using a complex object (javabean, entity, POJO, etc) as select item value instead of a standard type like
Long
for which JSF has builtin converters, then the same rules also apply. You only need to create a customConverter
and explicitly specify it in input component'sconverter
attribute, or rely onforClass
if you can useT[]
. How to create such a converter is elaborated in Conversion Error setting value for 'null Converter'.这篇关于列表< T>上的UISelectMany.导致java.lang.ClassCastException:java.lang.String无法转换为T的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!