入力パラメータがnullの場合、compareTo()はNullPointerExceptionをスローする必要があると言われています。ただし、フィールドを文字列の型と比較する必要があるクラスを実装しています。これらのフィールドは必須である必要はありません。この場合、私は疑問に思います、
1)入力がnullの場合、何を返す必要がありますか? null以外の文字列は、辞書式にnullよりも大きいか小さい必要がありますか?
そして
2)これが悪い習慣と見なされる場合、裏付けとなる議論はありますか?代わりに空の文字列を使用するようにユーザーに強制する必要がありますか?空の文字列を使用する場合、フィールドが適用されない場合とフィールドが空の場合を混同しませんか?また、例外をスローする必要がある場合は、マニュアルでユーザーに警告する場合を除いて、他に何ができますか?
編集:ここでは自分自身を明確に表現できないかもしれませんが、実装しているプログラムでは、nullになる可能性のある文字列はすべてフィールドまたはクラスであり、nullであってはなりません。言い換えると、compareTo()が使用するオブジェクトをnullにすることはできず、プライベートフィールドのみをnullにすることができます。したがって、この場合、compareTo()を適切に実装すれば、nullフィールドを持つクラスは常に同じと見なされるため、推移的な要件に違反しないと思います。私は正しいですか、それとも私はこれを間違って解釈していますか?
答えてくれてありがとう!
はい、インスタンスフィールドにnull
を許可しても問題はありません。ソート順が定義されていることを確認してください。最も自然なのは、すべての実際の文字列の前または後に置くことですが、ここでは何でもできます。一貫して行うだけです。 (たとえば、null
を_"null"
_のように並べ替えることができます。)
単一メンバーの実装例を次に示します。
_class Example implements Comparable<Example> {
@Nullable
private String member;
// TODO: getter, setter, constructor, ...
public int compareTo(Example that) {
if(this.member == null)
if(that.member == null)
return 0; //equal
else
return -1; // null is before other strings
else // this.member != null
if(that.member == null)
return 1; // all other strings are after null
else
return this.member.compareTo(that.member);
}
}
_
Comparable.compareTo()の指定には、o.compareTo(null)
(- null.compareTo(o)
と同じように動作する、つまりNullPointerExceptionをスローする)の制約のみがあり、null
フィールドが処理されます(フィールドについてはまったく言及されていないため、反対称、再帰性、推移性が保証されている限り、クラスは必要なものを返すことができます)。
Javadocから Comparable
Nullはどのクラスのインスタンスでもないことに注意してください。また、e.equals(null)がfalseを返しても、e.compareTo(null)はNullPointerExceptionをスローする必要があります。
例外に違反しているため、例外をスローしないことは悪い習慣です。 推移的 compareToの反対称の性質。
から Comparable.compareTo ドキュメント:
実装者は、すべてのxとyに対してsgn(x.compareTo(y))== -sgn(y.compareTo(x))を確認する必要があります。 (これは、y.compareTo(x)が例外をスローする場合、x.compareTo(y)が例外をスローする必要があることを意味します。)
実装者は、関係が推移的であることも確認する必要があります。(x.compareTo(y)> 0 && y.compareTo(z)> 0)は、x.compareTo(z)> 0を意味します。
最後に、実装者は、すべてのzについて、x.compareTo(y)== 0がsgn(x.compareTo(z))== sgn(y.compareTo(z))を意味することを確認する必要があります。
さらに重要なことに、同じ理由で、オブジェクトでcompareToを使用して文字列と比較することはお勧めできません:sign(obj.compareTo(str)) != -sign(str.compareTo(obj))
。カスタムを実装する Comparator そしてあなたがやりたいことは何でもします。
compareTo
のドキュメントにはNullPointerException
をスローする必要があると記載されているため、実装がインターフェイスのドキュメントと一致するように、これらのガイドラインに従う必要があります。これは、null以外の文字列が辞書式にnull
よりも小さいか大きいかという問題も処理します。
これを処理する方法については、いくつかのオプションがあります。空と該当なしが異なる場合は、文字列フィールドを独自のフィールドクラスでラップする必要があります。たとえば、isApplicable
メソッドを持つ可能性のあるタイプのMyFieldを作成できます。これは、フィールドがこのケース(または同様のもの)に適用できるかどうかを示します。または、デザインを再考して、空の文字列とN/Aが実際には2つの異なるものであることを確認することもできます。もしそうなら、あなたは2つを区別する方法が必要です。
Nullがnull以外の値よりも大きいか小さいかを判断する必要があります。クラスの自然順序付けのニーズを満たすようにcompareTo
を設計できるため、悪い習慣ではありません。