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>并且我正在调用contains传递Long.valueOf值的方法,我怎么能得到这个异常?

这是 JSF 应用程序的模型 bean。我正在使用 Java 6、Tomcat 6.0.32、mojarra 2.1.14,但这些都不应该真正重要,因为泛型应该防止这种问题的编译时间......

- - - - - - - 编辑 - - - - - - - - -

它实际上是 JSF ......我用这个 setter 组合了一个超级简化的例子:

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 强调这一点)。使用包含s 的a调用setter 。那么现在,转换的最佳过程是什么?我是否需要遍历将每个值转换为 Long 的列表?SetString

附带说明一下,我使用 Java 7 在 Tomcat 7 上对此进行了测试,ClassCastException 消失了,但是,该contains方法总是false按预期返回。

-------------- 编辑 2 -----------------

我在这里找到了正确绑定我的组件的方法的答案。

-------------- 编辑 3 -----------------

这是对问题的更好解释

4

2 回答 2

5

也许我遗漏了一些东西,但是如果声明是 Set 并且我正在调用包含 Long.valueOf 值的 contains 方法,我怎么能得到这个异常?

请注意,在 Java 中,泛型类型注解只是对编译器的提示,在运行时不起作用,因此在运行时可能会违反这些约束(但在某处会出现编译器警告)。

看起来您Set<Long>实际上至少包含一个字符串。那个 Set 是从哪里来的?

因为泛型应该防止这种问题的编译时间

是的,您的代码中应该有关于缺少泛型类型或未经检查的强制转换的警告。这只是一个警告,因为泛型是可选的。在您确实使用它们的地方,这将是一个错误。

于 2012-12-27T01:40:29.400 回答
0

好的@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 回答