首先在Java 1.7中的TreeSet上添加调用compareTo

我有一个TreeSet元素,并根据:

http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html#compareTo%28T%29

[当且仅当e1.compareTo(e2)== 0与e1.equals(e2)具有相同的布尔值时,类C的自然顺序被认为与等于一致。对于类C的每个e1和e2 null不是任何类的实例, 即使e.equals(null)返回falsee.compareTo(null)也应抛出NullPointerException。 ]

Element类具有非空安全的compareTo方法

我有以下代码在Java 1.5上工作,但不在Java 1.7中

  • 为什么我需要做一个空安全compareTo? 为什么javadoc这样说?
  • 为什么compareTo方法首先在Java 1.7中添加调用,但在1.5中没有调用?
  • @Test
    public void simpleTest() {
        try {
            Collection<Element> set = new TreeSet<Element>();
            Element cv = new Element(null);
            set.add(cv);//first add throws NPE (calling to compareTo())
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private class Element implements Comparable<Element> {
        private final String attr;
    
        public Element(String attr) {
            super();
            this.attr = attr;
        }
    
        @Override
        public int hashCode() {
            System.out.println("executing hashCode...");
            final int prime = 31;
            int result = 1;
            result = prime * result + getOuterType().hashCode();
            result = prime * result + ((attr == null) ? 0 : attr.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            System.out.println("executing equals...");
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Element other = (Element) obj;
            if (!getOuterType().equals(other.getOuterType()))
                return false;
            if (attr == null) {
                if (other.attr != null)
                    return false;
            } else if (!attr.equals(other.attr))
                return false;
            return true;
        }
    
        private CatalogoActionTest getOuterType() {
            return CatalogoActionTest.this;
        }
    
        public int compareTo(Element o) {
            System.out.println("executing compareTo...");
            //throw NPE when attr is null
            return this.attr.compareTo(o.attr);//line 182
        }
    }
    

    我想了解,如果compareTo需要为null安全,或者问题是构造一个新的对象与无效的数据。

    这是堆栈跟踪:

        java.lang.NullPointerException
        at com.MyTest$Element.compareTo(MyTest.java:182)
        at com.MyTest$Element.compareTo(MyTest.java:138)
        at java.util.TreeMap.compare(TreeMap.java:1188)
        at java.util.TreeMap.put(TreeMap.java:531)
        at java.util.TreeSet.add(TreeSet.java:255)
    

    嗯。 滑稽。 如果你检查TreeMap第531行,你会发现它将key和thist比较:

    compare(key, key);
    

    所以基本上它调用

    cv.compareTo(cv);
    

    它会因为cv中的attr为空而崩溃。 类Element没有正确实现compareTo 。 我想如果你将对象与抛出NPE的对象本身进行比较,它必须返回0。


    在Java 7中TreeSet / TreeMap行为发生了变化。请考虑以下主要方法:

    import java.util.TreeSet;
    
    public class C {
    
      public static void main(String[] args) {
        TreeSet<Object> ts = new TreeSet<Object>();
        ts.add(null);
        System.out.println("TreeSet size is: " + ts.size());
      }
    
    }
    

    在Java 6上运行良好:

    $ java -showversion -cp . C
    java version "1.6.0_45"
    Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
    Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
    
    TreeSet size is: 1
    

    Java 7的发展:

    $ java -showversion -cp . C
    java version "1.7.0_55"
    Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
    Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)
    
    Exception in thread "main" java.lang.NullPointerException
        at java.util.TreeMap.compare(TreeMap.java:1188)
        at java.util.TreeMap.put(TreeMap.java:531)
        at java.util.TreeSet.add(TreeSet.java:255)
        at C.main(C.java:7)
    
    链接地址: http://www.djcxy.com/p/76219.html

    上一篇: compareTo triggered at first add call on TreeSet in Java 1.7

    下一篇: Why is this not throwing a NullPointerException?