compareTo在Java 1.7中对TreeSet的第一次添加调用时触发



我有一个包含元素的TreeSet,根据:

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

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

元素类具有非空安全比较到方法

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

  • 为什么我需要进行Null安全比较?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行,你会发现它将密钥与其自身进行比较:

compare(key, key);

所以基本上它调用

cv.compareTo(cv);

并且由于cv中的attr为空,所以它被压碎。类Element没有正确实现compareTo。如果您将对象和抛出NPE的自身进行比较,我想它必须返回0。

树集/树映射行为在Java 7中发生了更改。考虑以下主要方法:

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)

相关内容

  • 没有找到相关文章

最新更新