这不完全是 Java 的错。泛型类型信息只是在运行时丢失。Java/JSF/EL 不在编译时运行,而是在运行时运行。它在运行时看到的只是 a Set,而不是Set<Long>.
当 JSF 将提交的输入值设置为 bean 属性时,它首先检索它们,String因为这是 的默认返回类型request.getParameter(),JSF 在幕后使用它来获取请求参数。只要没有指定转换器,JSF 就会在via 反射中设置那些String未转换的提交值。Set这基本上是“幕后”发生的事情:
package com.stackoverflow.q14521882;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class Test {
private Set<Long> set = new HashSet<Long>();
public static void main(String[] args) throws Exception {
Test test = new Test();
Field field = test.getClass().getDeclaredField("set");
Object object = field.get(test);
if (object instanceof Collection) {
((Collection) object).add("string");
}
System.out.println(test.set.iterator().next().getClass()); // CCE!
}
}
Long[]当您使用而不是 时,它会起作用Set<Long>,但鉴于它Set首先是,您只想保留唯一值,Long[]因此可能不是一个选项。为了解决它,您需要Converter在输入组件中显式指定 a 。您可以为此使用内置的 JSF LongConverter,它的转换器 ID 为javax.faces.Long:
<h:selectManyListbox ... converter="javax.faces.Long">