调用TreeSet时发生ClassCastException

调用TreeSet时发生ClassCastException

本文介绍了调用TreeSet时发生ClassCastException< Long> .contains(Long.valueOf(someLongValue))的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我陷入困境。我这样宣布自己的设置:

  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);
}
}
}
}
返回应用程序;
}

我最终得到这个结果:

  java.lang.ClassCastException:无法将java.lang.String强制转换为java.lang.Long $ b $ java.lang.Long.compareTo(Long。 java:50)
在java.util.TreeMap.getEntry(TreeMap.java:346)$ b $在java.util.TreeMap.containsKey(TreeMap.java:227)$ b $在java.util .TreeSet.contains(TreeSet.java:234)
at org.mitre.asias.pf.pnp.viewmodel.Subscription.getApplications(Subscription.java:84)

导致异常的行(来自堆栈跟踪的第84行)是这样的:



<$ p $ (application.getId()))){

也许我错过了一些东西,但是如果声明是 Set< Long> ,并且我调用 contains 方法传入一个 Long.valueOf 值,我该如何得到这个异常?



这是上午用于JSF应用程序的odel 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(\\\
\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  - 选定的值:
'java.lang.String ':'1'
'java.lang.String':'5'

,简单的答案是正确的(谢谢@PaulTomblin强调这一点)。使用包含 String s的 Set 调用setter 。那么现在,转换的最佳过程是什么?我需要遍历列表将每个值转换为Long吗?



作为附注,我使用Java 7在Tomcat 7上测试了这一点,并且ClassCastException消失了,但是,包含方法总是会返回 false ,这应该是预期的。



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



我找到了一个答案,以正确的方式绑定我的组件。



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



而是对问题的更好解释。

解决方案

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

看起来像你的 Set< Long> 实际上至少包含一个String。这个Set来自哪里?

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


Im stumped. I declare my set thusly:

    private Set<Long> applicationIds;

Then I populate it like this:

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

Then I attempt to use it:

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;
}

And I end up with this:

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)

The line causing the exception (line 84 from the stack trace) is this one:

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

Perhaps I am missing something, but if the declaration is Set<Long> and I am calling the contains method passing in a Long.valueOf value, how can I be getting this exception?

This is a model bean for a JSF application. I am using Java 6, Tomcat 6.0.32, mojarra 2.1.14, but none of that should really matter as the Generics are supposed to prevent this kind of problem compile time...

-------------- EDIT -----------------

Its actually the JSF... I threw together a super simplified example with this 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;
}

bound to this component:

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

which writes this to the log:

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'

So, the simple answer is the correct one (thank you @PaulTomblin for emphasizing this). The setter is getting called with a Set that contains Strings. So now, what is the best process for conversion? Will I need to iterate through the list casting each value to a Long?

As a side note, I tested this on Tomcat 7 using Java 7 and the ClassCastException went away, however, the contains method always returns false as should be expected.

-------------- EDIT 2 -----------------

I found an answer with the correct way to bind my component here.

-------------- EDIT 3 -----------------

And here is a better explanation of the problem.

解决方案

Note that in Java, generic type annotations are only hints for the compiler and have no effect at runtime, so it is possible to violate these constraints at runtime (but there will be a compiler warning somewhere).

Looks like your Set<Long> actually contains at least one String. Where is that Set coming from?

Yes, there should be a warning somewhere in your code about missing generic types or unchecked casts. It is only a warning because generics are optional. In the places where you did use them, it would have been an error.

这篇关于调用TreeSet时发生ClassCastException&lt; Long&gt; .contains(Long.valueOf(someLongValue))的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-09 03:50