我的代码中有一个非常奇怪的错误。我从项目开始就使用迭代器,我从来没有遇到过问题,但在这里我无法理解发生了什么。
我有一个模型类
public class MyObject implements Serializable{
private static final long serialVersionUID = 1L;
private int field1;
private String field2;
private List<OtherObject> field3;
private Date field4
...
// + Getters and setters
// + Override equals method
}
参数为MyObject type
的类public class FooClass implements Serializable{
private static final long serialVersionUID = 1L;
private List<MyObject> list;
// + getters and setters
}
我还有另一个使用MyObject的课程
public class MyController {
.....
public static void AMethod(FooClass value) {
List<MyObject> myList = value.getList();
Iterator<MyObject> iterator = myList.iterator();
while(iterator.hasNext()) {
MyObject temp = iterator.next(); // error on this line
}
}
...
}
我的对象使用以下代码显示在JSF视图中:
<p:selectCheckboxMenu value="#{fooClass.list}">
<f:selectItems value="#{fooClass.listAll}" var="obj"
itemValue="#{obj}" itemLabel="#{obj.field2}" />
</p:selectCheckboxMenu>
这是我得到的错误:
java.lang.ClassCastException: java.lang.String cannot be cast to com.MyObject
有任何建议吗?
答案 0 :(得分:2)
这是因为HTTP协议的“设计”:当请求发送到服务器时,所有数据都以String
的形式发送。因此,JSF也将它们解释为String
,因为在您的情况MyObject
中,您没有明确告诉您期望的对象是您的特定类。这是因为处理所有视图模型通信的EL基于反射,并且您知道Java中的泛型是由于类型擦除而导致的编译时现象:通用信息在运行时不可用。
因此,基本上在您提交表单后,您的列表包含普通String
对象,而不是您的MyObject
实例,正如您所期望的那样:在提交表单后,JSF EL会替换通用信息。这就是你得到ClassCastException
的原因。如果在动作(侦听器)方法或setter方法上放置断点,则可以自己检查列表中包含的元素类型。
要解决这种情况,您需要明确告诉JSF使用Converter
(通过指定converter
属性,或嵌套<f:converter>
标记),或切换到plain array(到MyObject[]
)而不是List<MyObject>
。
您可以在我对JSF and type safety问题的回答中找到更多信息以及一些解决方案。