2

私は要素を持つ TreeSet を持っています。

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

[ クラス C の自然順序付けは、e1.compareTo(e2) == 0 がクラス C のすべての e1 および e2 に対して e1.equals(e2) と同じブール値を持つ場合にのみ、equals と一致すると言われます。 null はどのクラスのインスタンスでもなく、e.equals(null) が false を返す場合でも、e.compareTo(null) は NullPointerException をスローする必要があります。 ]

要素クラスには null セーフでない compareTo メソッドがあります

Java 1.5 で動作する次のコードがありますが、Java 1.7 では動作しません。

  • Null Safe の compareTo を実行する必要があるのはなぜですか? そして、なぜjavadocはそれを言うのですか?
  • Java 1.7では最初の追加呼び出しでcompareToメソッドがトリガーされたのに、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)
4

2 に答える 2

3

うーん。面白い。の 531 行目を確認TreeMapすると、キーとそれ自体が比較されていることがわかります。

compare(key, key);

したがって、基本的には呼び出します

cv.compareTo(cv);

そして、attrincvが null であるため、クラッシュします。クラスが正しくElement実装されていません。compareToオブジェクトをNPEをスローするそれ自体と比較すると、0を返さなければならないと思います。

于 2013-12-02T16:36:43.783 に答える