0

私は困惑しています。私は自分のセットを次のように宣言します。

    private Set<Long> applicationIds;

次に、次のように入力します。

public void setApplicationIds( Set<Long> applicationIds ) {
    this.applicationIds = new TreeSet<Long>( applicationIds );
    this.applications = null;
}

それから私はそれを使用しようとします:

public List<Application> getApplications() {
    if ( applications == null ) {
        applications = new ArrayList<Application>();
        if ( applicationIds != null ) {
            for ( Application application : availableApplications ) {
                if ( applicationIds.contains( Long.valueOf( application.getId() ) ) ) {
                    applications.add( application );
                }
            }
        }
    }
    return applications;
}

そして、私はこれで終わります:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
    at java.lang.Long.compareTo(Long.java:50)
    at java.util.TreeMap.getEntry(TreeMap.java:346)
    at java.util.TreeMap.containsKey(TreeMap.java:227)
    at java.util.TreeSet.contains(TreeSet.java:234)
    at org.mitre.asias.pf.pnp.viewmodel.Subscription.getApplications(Subscription.java:84)

例外の原因となっている行 (スタック トレースの 84 行目) は次のとおりです。

                if ( applicationIds.contains( Long.valueOf( application.getId() ) ) ) {

おそらく何かが足りないのですが、宣言があり、値を渡すメソッドをSet<Long>呼び出している場合、どうすればこの例外を取得できますか?containsLong.valueOf

これは、JSF アプリケーションのモデル Bean です。私はJava 6、Tomcat 6.0.32、mojarra 2.1.14を使用していますが、ジェネリックはこの種の問題のコンパイル時間を防ぐことになっているため、実際には問題になりません...

- - - - - - - 編集 - - - - - - - - -

それは実際にはJSFです...私はこのセッターで非常に単純化された例をまとめました:

public void setSelectedValues(Set<Long> selectedValues) {
    this.selectedValues = selectedValues;
    if (logger.isTraceEnabled()) {
        StringBuilder message = new StringBuilder("Selected values:");
        for (Object value : selectedValues) {
            message.append("\n\t'").append(value.getClass().getName())
                    .append("': '").append(value.toString()).append("'");
        }
        logger.trace(message.toString());
    }
    this.selections = null;
}

このコンポーネントにバインド:

<p:selectManyCheckbox id="numbers"
   value="#{controller.selectedValues}" layout="pageDirection">
  <f:selectItems value="#{controller.availableValues}" />
</p:selectManyCheckbox>

これはこれをログに書き込みます:

15:45:16.887 [http-bio-8080-exec-9] TRACE com.pastdev.learn.debug.Controller - Selected values:
    'java.lang.String': '1'
    'java.lang.String': '5'

したがって、簡単な答えが正しいものです(これを強調してくれた@PaulTomblinに感謝します)。セッターSet、sを含むa で呼び出されていますString。では、変換に最適なプロセスは何ですか? 各値を Long にキャストしてリストを反復処理する必要がありますか?

補足として、Java 7 を使用して Tomcat 7 でこれをテストしたところ、ClassCastException はなくなりましたが、containsメソッドは常にfalse期待どおりに戻ります。

-------------- 編集 2 -----------------

ここで私のコンポーネントをバインドする正しい方法で答えを見つけました。

-------------- 編集 3 -----------------

そして、ここに問題のより良い説明があります。

4

2 に答える 2

5

おそらく何かが足りないのでしょうが、宣言が Set であり、Long.valueOf 値を渡して contains メソッドを呼び出している場合、どうすればこの例外を取得できますか?

Java では、ジェネリック型注釈はコンパイラのヒントにすぎず、実行時には影響しないため、実行時にこれらの制約に違反する可能性があることに注意してください (ただし、どこかにコンパイラの警告が表示されます)。

Set<Long>実際には少なくとも 1 つの文字列が含まれているようです。そのセットはどこから来たのですか?

Generics は、この種の問題のコンパイル時間を防止することになっているため

はい、コードのどこかに、ジェネリック型の欠落または未チェックのキャストに関する警告があるはずです。ジェネリックはオプションであるため、これは単なる警告です。それらを使用した場所では、エラーになります。

于 2012-12-27T01:40:29.400 に答える
0

OK @Lucas質問の一部として投稿したコードを使用して、すばやく汚いコードを使用してみましたが、正常に動作します。Applicationもう一度クラスを確認する必要があるかもしれません。

package javaapplication2;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class JavaApplication2 {


private static Set<Long> applicationIds;

private List<Application> applications;

private static final List<Application> availableApplications = new ArrayList<>();

public static void main(String[] args) {

    JavaApplication2 proj = new JavaApplication2();
    for (int i = 1; i <= 11; i++) {
        Application application = new Application();
        application.setId(i);
        availableApplications.add(application);
    }
    Set<Long> applicationIds1 = new TreeSet<>();
    applicationIds1.add(11L);
    applicationIds1.add(12L);
    applicationIds1.add(13L);

    proj.setApplicationIds(applicationIds1);
    for (Application appl : proj.getApplications()) {
        System.out.println(appl.getId());
    }
}

public void setApplicationIds(Set<Long> applicationIds) {
    this.applicationIds = new TreeSet<Long>(applicationIds);
    this.applications = null;
}

public List<Application> getApplications() {
    if (applications == null) {
        applications = new ArrayList<Application>();
        if (applicationIds != null) {

            for (Application application : availableApplications) {
                if (applicationIds.contains(Long.valueOf(application.getId()))) {
                    applications.add(application);
                }
            }
        }
    }
    return applications;
}

}

と:

package javaapplication2;

class Application {
private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

}
于 2012-12-27T02:09:31.367 に答える