compareTo triggered at first add call on TreeSet in Java 1.7
我有一个包含元素的树集,根据:
http://DOCS.Oracle .COM/JavaSe/ 7 /DOCS/API/Java/Lang/可比。
[当且仅当e1.compareto(e2)==0的布尔值与e1.equals(e2)对于类C的每个e1和e2的布尔值相同时,类C的自然顺序才被称为与equals一致。请注意,空值不是任何类的实例,并且e.compareto(null)应引发nullpointerException,即使e.equals(null)返回false。]
元素类具有非空的安全CompareTo方法
我有以下代码在Java 1.5上工作,但是在Java 1.7中没有
- 为什么我需要做一个空安全比较?为什么JavaDoc这么说?
- 为什么首先在Java 1.7中添加调用,但在1.5中不触发?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | @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是否需要空安全,或者问题是用无效数据构造一个新对象。
这是stacktrace:
1 2 3 4 5 6 |
嗯,好笑。如果您检查EDOCX1的第531行(0),您将看到它将key与其elft进行比较:
1 | compare(key, key); |
所以基本上它调用
1 | cv.compareTo(cv); |
因为
TraceSe/TreMeAP行为在Java 7中发生了变化。考虑以下主要方法:
1 2 3 4 5 6 7 8 9 10 11 |
在Java 6上运行良好:
1 2 3 4 5 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上爆炸:
1 2 3 4 5 6 7 8 9 10 | $ 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) |