[英]ClassCastException when calling TreeSet<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 );
}
}
}
}
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
值的contains
方法,那么我該如何獲取此異常?
這是用於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
包含String
秒。 那么,現在最好的轉換過程是什么? 我是否需要遍歷整個列表,將每個值都轉換為Long?
附帶說明一下,我使用Java 7在Tomcat 7上對此進行了測試,但ClassCastException消失了,但是, contains
方法總是返回false
,這與預期的一樣。
--------------編輯2 -----------------
我發現我的組件綁定正確的方式回答這里 。
--------------編輯3 -----------------
這是對該問題的更好解釋。
也許我缺少了一些東西,但是如果聲明是Set,並且我正在調用傳遞Long.valueOf值的contains方法,那么我該如何獲取此異常?
請注意,在Java中,泛型類型注釋僅是編譯器的提示,在運行時不起作用,因此有可能在運行時違反這些約束(但在某處會出現編譯器警告)。
看起來您的Set<Long>
實際上包含至少一個String。 那套東西從哪里來?
因為泛型應該避免這種問題的編譯時間
是的,您的代碼中應該有一個警告,指出缺少通用類型或未經檢查的強制類型轉換。 這只是一個警告,因為泛型是可選的。 在您確實使用過的地方,那將是一個錯誤。
好的,@ 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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.