我只是在尝试 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
所选类别的 a:
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;
}
}
此外,我将查看可能讨论完全相同问题的链接问题。