我很难过。我这样声明了我的一套:
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强调这一点)。使用包含Set
的{{1}}调用setter 。那么现在,转换的最佳流程是什么?我是否需要遍历列表,将每个值转换为Long?
作为旁注,我使用Java 7在Tomcat 7上对此进行了测试,并且ClassCastException消失了,但String
方法始终返回contains
,这应该是预期的。
--------------编辑2 -----------------
我找到了一个答案,其中包含绑定我的组件here的正确方法。
--------------编辑3 -----------------
here是对问题的更好解释。
答案 0 :(得分:5)
也许我遗漏了一些东西,但是如果声明是Set并且我正在调用传入Long.valueOf值的contains方法,那么我怎么能得到这个异常呢?
请注意,在Java中,泛型类型注释只是编译器的提示,并且在运行时没有任何影响,因此可能在运行时违反这些约束(但在某处会有编译器警告)。
看起来您的Set<Long>
实际上至少包含一个字符串。 Set来自何处?
因为泛型应该防止这种问题编译时间
是的,代码中应该有关于缺少泛型类型或未经检查的强制转换的警告。这只是一个警告,因为泛型是可选的。在您使用它们的地方,这将是一个错误。
答案 1 :(得分: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;
}
}