我有一个包含<h:selectManyMenu>
元素的JSF页面。value属性指向在子类中定义为ArrayList<String>
类型的泛型对象。根据java文档,UISelectMany
应该将转换后的值返回为这种具体类型的Collection
。但它是作为String[]
数组返回的。我错过了什么?
<h:selectManyMenu value="#{parameter.value}">
<f:selectItems value="#{parameter.valueList}"/>
</h:selectManyMenu>
public class Parameter<ArrayList<String>> extends ParentClass
{
private LinkedHashMap<Object, String> valueList;
public List<SelectItem> getValueList()
{
ArrayList<SelectItem> list = new ArrayList<SelectItem>();
for (Iterator<Object> i = this.valueList.keySet().iterator(); i.hasNext();)
{
Object value = i.next();
list.add(new SelectItem(value, this.valueList.get(value)));
}
return list;
}
}
public abstract class ParentClass<T>
{
private T value;
public T getValue() { return this.value; }
public void setValue(T t) { this.value = t; }
}
这是因为getValue()
返回一个参数化类型T
,该类型将在泛型擦除后变为Object
。换句话说,EL没有看到它实际上返回的是List
,而是Object
,因此将默认为String[]
。
您需要显式地在选择组件上指定collectionType
属性,并将所需集合实现的FQN作为值。
<h:selectManyMenu ... collectionType="java.util.ArrayList">
与具体问题无关,<f:selectItems>
也支持Map<K, V>
。只需将LinkedHashMap
直接提供给它,而无需将其按摩到List<SelectItem>
。映射键成为选项值,映射值已经成为选项标签。参见selectOneMenu
wiki页面
我无法让JSF从子类中读取属性的类型定义。指定collectionType
属性不起作用,甚至当尝试在子类中创建@Override
方法时,发送给bean的支持值仍然是一个String[]
数组。我能够让JSF servlet以ArrayList<String>
的形式返回这个值的唯一方法是在子类中创建另外一对get/set属性方法,并将ArrayList<String>
作为它们的返回值和参数类型。
public class Parameter extends ParentClass<ArrayList<String>>
{
public ArrayList<String> getManyValue() { return super.getValue(); }
public void setManyValue(ArrayList<String> value) { super.setValue(value); }
}
public abstract class ParentClass<T>
{
protected T value;
public T getValue() { return this.value; }
public void setValue(T value) { this.value = value; }
}
<h:selectManyMenu value="#{parameter.manyValue}"/>