0

java.lang.Comparable#compareToメソッドは最初のプロビジョニングとして述べています

実装者は、すべてのxとyに対してsgn(x.compareTo(y))== -sgn(y.compare- To(x))を確認する必要があります。(これは、y.compareTo(x)が例外をスローする場合にのみ、x.compareTo(y)が例外をスローする必要があることを意味します。)

項目12のEffectiveJavaのJoshuaBlochによると

このトリックはここではうまく機能しますが、細心の注意を払って使用する必要があります。問題のフィールドが負でないことが確実であるか、より一般的には、可能な最小フィールド値と最大フィールド値の差がInteger.MAX_VALUE(231-1)以下であることが確実でない限り、これを使用しないでください。このトリックが常に機能するとは限らない理由は、符号付き32ビット整数が2つの任意の符号付き32ビット整数の差を保持するのに十分な大きさではないためです。iが大きな正の整数で、jが大きな負の整数の場合、(i --j)はオーバーフローし、負の値を返します。結果のcompareToメソッドは、一部の引数に対して誤った結果を返し、compareToコントラクトの最初と2番目の規定に違反します。これは純粋に理論的な問題ではありません。実際のシステムで障害が発生しています。これらの障害はデバッグが難しい場合がありますが、

整数がオーバーフローすると、最初の規定に違反する可能性があり、その方法がわかりません。この例は、最初の規定に違反する方法を示しています。

public class ProblemsWithLargeIntegers implements Comparable<ProblemsWithLargeIntegers> {

    private int zas;

    @Override
    public int compareTo(ProblemsWithLargeIntegers o) {
        return zas - o.zas;
    }

    public ProblemsWithLargeIntegers(int zas) {
        this.zas = zas;
    }

    public static void main(String[] args) {
      int value1 = ...;
      int value2 = ...;
      ProblemsWithLargeIntegers d = new ProblemsWithLargeIntegers(value1);
      ProblemsWithLargeIntegers e = new ProblemsWithLargeIntegers(value2);
      if (!(Math.signum(d.compareTo(e)) == -Math.signum(e.compareTo(d)))){
        System.out.println("hey!");
    }

}

だから私はそれを得るためにvalue1とが欲しいvalue2ですか?何か案が?またはジョシュアは間違っていましたか?

4

1 に答える 1

3

さて、これはそもそも一般契約に違反します。たとえば、とを取りvalue1 = Integer.MIN_VALUEますvalue2 = 1Integer.MIN_VALUE > 1それは、効果的にそれを報告します。

編集:実際、私は間違っていました-最初の規定に違反するのは簡単です:

int value1 = Integer.MIN_VALUE;
int value2 = 0;

Integer.MIN_VALUE - 0==であるため、両方の比較で負の結果が得られます0 - Integer.MIN_VALUE

于 2012-07-26T16:26:39.773 に答える