这不完全是 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">