簡體   English   中英

UISelectMany在列表上 <T> 導致java.lang.ClassCastException:java.lang.String無法轉換為T

[英]UISelectMany on a List<T> causes java.lang.ClassCastException: java.lang.String cannot be cast to T

我在List<Long>上使用<p:selectCheckboxMenu> List<Long>

<p:selectCheckboxMenu value="#{bean.selectedItems}">
    <f:selectItems value="#{bean.availableItems}" />
</p:selectCheckboxMenu>
private List<Long> selectedItems;
private Map<String, Long> availableItems;

提交表單並按以下方式遍歷所選項目時,

for (int i = 0; i < selectedItems.size(); i++) {
    Long id = selectedItems.get(i);
    // ...
}

然后我得到一個類強制轉換異常:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
    at com.example.Bean.submit(Bean.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:278)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    ... 27 more

<p:selectManyCheckbox><p:selectManyMenu><h:selectManyMenu>等也會發生相同的問題。基本上,所有多選組件均如此。 <p:selectOneMenu>和單個值Long屬性上的所有其他單選組件中,它可以正常工作。

這是怎么引起的,我該如何解決?

您的問題是由以下事實引起的:

  1. Java泛型是編譯時的語法糖,在運行時完全不存在。
  2. EL表達式在運行時而不是編譯時運行。
  3. HTTP請求參數作為String 獲得

邏輯結果是:EL沒有看到任何通用類型信息。 EL沒有看到List<Long> ,但是看到List 因此,當您未明確指定轉換器時,EL將獲取提交的值作為String將其設置為通過反射方式未在List進行修改。 當您隨后嘗試在運行時將其ClassCastExceptionLong時,顯然會遇到ClassCastException

解決方案很簡單:為StringLong明確指定一個轉換器。 您可以為此使用JSF內置的LongConverter ,它具有轉換器ID javax.faces.Long 其他內置轉換器在此處列出。

<p:selectCheckboxMenu ... converter="javax.faces.Long">

無需顯式指定轉換器的另一種解決方案是將List<T>類型更改為T[] 這樣,EL將看到Long類型的數組,從而執行自動轉換。 但這可能需要在模型中的其他位置進行更改,這可能是不希望的。

private Long[] selectedItems;

如果您使用復雜的對象(javabean,實體,POJO等)作為選擇項值,而不是使用JSF內置轉換器的Long這樣的標准類型,則同樣的規則也適用。 您只需要創建一個自定義Converter並在輸入組件的converter屬性中顯式指定它,或者如果可以使用T[]則依賴於forClass “空轉換器”的“轉換錯誤”設置值中詳細說明了如何創建此類轉換

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM