4

私はで使用<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

これはどのように発生し、どうすれば解決できますか?

4

1 に答える 1

9

あなたの問題は、次の事実によって引き起こされます。

  1. Java ジェネリックはコンパイル時のシンタックス シュガーであり、実行時には完全に存在しません。
  2. EL 式は、コンパイル時ではなく実行時に実行されます。
  3. HTTP リクエスト パラメータはs として取得されStringます。

論理的な結果は次のとおりです。EL はジェネリック型情報を認識しません。EL には が表示されませんList<Long>が、List. したがって、コンバーターを明示的に指定しない場合、EL は、送信された値を取得した後、リフレクション手段Stringで変更されないように設定しListます。実行時に後でキャストしようとすると、明らかに.LongClassCastException

String解決策は簡単です。 toのコンバーターを明示的に指定しますLongLongConverterこれには、コンバーター ID を持つJSF ビルトインを使用できますjavax.faces.Long。その他の組み込みコンバーターは、こちらにリストされています。

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

コンバーターを明示的に指定する必要のない別の解決策は、List<T>タイプを aに変更することT[]です。このようにして、EL はLong型付き配列を認識し、自動変換を実行します。しかし、これには、モデルの他の場所で望ましくない変更が必要になる可能性があります。

private Long[] selectedItems;

JSF にコンバーターが組み込まれているような標準タイプの代わりに、複雑なオブジェクト (javabean、エンティティ、POJO など) を選択項目の値として使用している場合Longは、同じ規則が適用されます。カスタムを作成し、Converterそれを入力コンポーネントの属性で明示的に指定するか、使用できる場合はconverterに依存するだけです。このようなコンバーターを作成する方法は、「null コンバーター」の変換エラー設定値で詳しく説明されています。forClassT[]

于 2013-11-09T11:13:46.640 に答える