我只是尝试了JSF,遇到了丑陋的ClassCastException
。
我有一个托管Bean(CustomerBean
),它有一个POJO(Customer
),用于存储用户数据。 POJO的一个属性是List<CathegoryType.Type> preferredCathegories
(带有getter和setter)。 CathegoryType
是一个模型类,它提供了导管(通过嵌套的enum Type
)及其本地化名称(通过方法getCathegory(Type type)
)。
现在,我有一个JSF页面来输入一些用户数据(editCustomer.xhtml
)。有一节可以选择首选的导管。选择导管的JSF代码如下所示:
<h:selectManyListbox
id="pcat"
value="#{customerBean.customer.preferredCathegories}"
styleClass="form-control">
<f:selectItems
value="#{customerBean.cathegoryTypes}">
</f:selectItems>
</h:selectManyListbox>
字段List<SelectItem> CustomerBeand.cathegoryTypes
提供枚举文字到其名称new SelectItem(type, CathegoryType.getCathegory(type))
的映射。现在有一个棘手的部分抛出ClassCastException
(在我的理解中无缘无故!)
当我提交表单时,另一个JSF页面(showCustomer.xhtml
)应该显示刚刚输入的用户数据。但是创建视图会因抛出以下ClassCastException而终止:
SCHWERWIEGEND: Servlet.service() for servlet [Faces Servlet] in context with path [/...] threw exception [java.lang.String cannot be cast to ...CathegoryType$Type] with root cause
java.lang.ClassCastException: java.lang.String cannot be cast to ...CathegoryType$Type
at ...CustomerBean.getNamedPreferredCathegories(CustomerBean.java:247)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
要显示所选的导管,showCustomer.xhtml
会调用方法String CustomerBean.getNamedPreferredCathegories()
:
<h:outputText value="#{customerBean.namedPreferredCathegories}" />
此方法计算所选导管的String
:
def String getNamedPreferredCathegories() {
val StringBuilder names = new StringBuilder
val List<CathegoryType.Type> cathegories = customer.preferredCathegories
val ListIterator<CathegoryType.Type> iter = cathegories.listIterator
var boolean first = true
while (iter.hasNext) {
val CathegoryType.Type cat = iter.next
val String name = cathegoryType.getCathegory(cat)
if(first) first = false else names.append(', ')
names.append(name)
}
return names.toString
}
我正在使用 Xtend 编程语言。它是一种JVM语言(编译为Java代码),因此与 Java类型系统完全兼容。我试图尽可能像Java一样编写这个方法,通常可以在一行中完成:
def String getNamedPreferredCathegories() {
'''«FOR name : customer.preferredCathegories.map[cathegory] SEPARATOR ', '»«name»«ENDFOR»'''.toString
}
因为我对列表进行了任何迭代,所以抛出了ClassCastException
......但是正如我所看到的,我没有在我的代码中执行任何强制转换操作!那么异常来自哪里?
我在Tomcat 8.5.9上运行该项目。
修改 好的,生成的Xtend方法的Java方法如下:
public String getNamedPreferredCathegories() {
final StringBuilder names = new StringBuilder();
final List<CathegoryType.Type> cathegories = this.customer.getPreferredCathegories();
final ListIterator<CathegoryType.Type> iter = cathegories.listIterator();
boolean first = true;
while (iter.hasNext()) {
{
final CathegoryType.Type cat = iter.next(); // Exception is thrown here!
final String name = this.cathegoryType.getCathegory(cat);
if (first) {
first = false;
} else {
names.append(", ");
}
names.append(name);
}
}
return names.toString();
}
在标记的行(final CathegoryType.Type cat = iter.next();
)中抛出异常。另外,生成的相关Customer
类的Java部分是:
public class Customer {
private List<CathegoryType.Type> preferredCathegories;
public List<CathegoryType.Type> getPreferredCathegories() {
return this.preferredCathegories;
}
public void setPreferredCathegories(final List<CathegoryType.Type> preferredCathegories) {
this.preferredCathegories = preferredCathegories;
}
}
此外,我将查看可能讨论完全相同问题的链接问题。