Java 为什么TreeSet';s add方法在不同的JRE中表现不同?

Java 为什么TreeSet';s add方法在不同的JRE中表现不同?,java,set,classcastexception,treeset,Java,Set,Classcastexception,Treeset,我尝试将Employee类的对象添加到树集。我没有实现Comparable或Comparator接口。但是add方法代码在不同的系统中表现不同。为什么会这样?下面的代码片段:- import java.util.Set; import java.util.TreeSet; public class TreeSetTest { public static void main(String[] args) { Set<Employee> set = new TreeSet&l

我尝试将Employee类的对象添加到树集。我没有实现Comparable或Comparator接口。但是add方法代码在不同的系统中表现不同。为什么会这样?下面的代码片段:-

import java.util.Set;
import java.util.TreeSet;

public class TreeSetTest {
public static void main(String[] args) {

    Set<Employee> set = new TreeSet<Employee>();
    set.add(new Employee());
//  set.add(new Employee());
//  set.add(new Employee());
 }
}
import java.util.Set;
导入java.util.TreeSet;
公共类树集{
公共静态void main(字符串[]args){
Set=新树集();
set.add(新员工());
//set.add(新员工());
//set.add(新员工());
}
}
在当前系统(Win 10)上,无论我编写set.add()方法一次还是三次。它总是在运行时抛出ClassCastException。 但说到这个问题—— 那里的用户写道,当他只使用一次add方法时,不会出现异常

另外,在另一个系统(Win7)中,昨天我尝试了三次添加对象,三次调用set方法,并且没有ClassCastException!!集合的大小仅为1,因此似乎没有将多个对象添加到集合中

那么,add方法的不同行为的原因是什么呢?

TreeSet.add()
委托给
TreeMap.put()
,它在Java 6和Java 8中的行为不同

:

public V put(K键,V值){
条目t=根;
如果(t==null){
//待定:
//5045147:(coll)向空树集添加null应该
//抛出NullPointerException
//
//比较(键,键);//类型检查
root=新条目(键、值、空);
尺寸=1;
modCount++;
返回null;
}
...
:

public V put(K键,V值){
条目t=根;
如果(t==null){
比较(key,key);//类型(可能为null)检查
root=新条目(键、值、空);
尺寸=1;
modCount++;
返回null;
}
...
正如您所看到的,早期版本出于某种原因注释掉了
compare()
行,但它被添加回了更高版本。因此,您看到的第一个元素的异常

请参见此处:

TreeSet.add()
委托到
TreeMap.put()
,它在Java6和Java8中具有不同的行为

:

public V put(K键,V值){
条目t=根;
如果(t==null){
//待定:
//5045147:(coll)向空树集添加null应该
//抛出NullPointerException
//
//比较(键,键);//类型检查
root=新条目(键、值、空);
尺寸=1;
modCount++;
返回null;
}
...
:

public V put(K键,V值){
条目t=根;
如果(t==null){
比较(key,key);//类型(可能为null)检查
root=新条目(键、值、空);
尺寸=1;
modCount++;
返回null;
}
...
正如您所看到的,早期版本出于某种原因注释掉了
compare()
行,但它被添加回了更高版本。因此,您看到的第一个元素的异常


另请参见此处:

如果有的话,它将是JRE版本,而不是Windows版本。@shmosel是的,所以我猜不同的Windows版本也会有不同的JRE。它们可能有,也可能没有。为什么不检查一下?@TimBiegeleisen是的,我只是从我的系统复制粘贴了它。运行Java 8的Win 10,但运行1.6版本的project。如果您已经这样做了知道错误的原因,即在构造过程中没有实现
Comparable
或提供自定义比较器,那么为什么要问这个问题?请注意,在添加第二项之前,实际上不需要进行排序比较。Java 6和Java 8之间的实现可能有轻微变化。无论如何,在没有比较器概念的情况下,你不应该使用排序集。如果有的话,它应该是JRE版本,而不是Windows版本。@shmosel是的,所以我猜不同的窗口版本也会有不同的JRE。它们可能有,也可能没有。为什么不检查一下?@TimBiegeleisen是的,我只是从我的系统复制粘贴了它。运行Win 10Java 8,但项目运行在1.6版本上。如果您已经知道错误的原因,即在构建过程中没有实现
Comparable
或提供自定义比较器,那么为什么要问这个问题?请注意,在添加第二项之前,实际上不需要进行订购比较。可能有一点变化在Java 6和Java 8之间的实现中。在任何情况下,如果没有比较器的概念,您都不应该使用排序集。很有趣。谢谢。让我阅读类的实现细节,以便更清晰。非常感谢这个答案。我快速查看了TreeMap类的实现,您非常满意这一点非常正确。在Java 6中,compare方法有注释,但在Java 7和8中没有注释。因此,它将在Java 7和8中抛出ClassCastException,但在6.0中没有。非常有趣。谢谢。让我阅读类的实现细节,以便更清晰。非常感谢您的回答。我快速查看了实现在Java 6中,compare方法被注释,但在Java 7和8中没有注释。因此,它将在Java 7和8中抛出ClassCastException,而不是在Java 6中抛出ClassCastException。
public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        // TBD:
        // 5045147: (coll) Adding null to an empty TreeSet should
        // throw NullPointerException
        //
        // compare(key, key); // type check
        root = new Entry<K,V>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    ...
public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    ...