a < b
およびa - b < 0
は、2つの異なることを意味する可能性があります。次のコードを検討してください:
int a = Integer.MAX_VALUE;
int b = Integer.MIN_VALUE;
if (a < b) {
System.out.println("a < b");
}
if (a - b < 0) {
System.out.println("a - b < 0");
}
これを実行すると、a - b < 0
が印刷されます。何が起こるかは、a < b
が明らかにfalseですが、a - b
がオーバーフローし、-1
になります。これは負の値になります。
今、アレイの長さは実際にはInteger.MAX_VALUE
に近いと考えています。 ArrayList
内のコードは次のようになります:
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
oldCapacity
がオーバーフローしてInteger.MIN_VALUE
(すなわち負)になるかもしれません(oldCapacity + 0.5 * oldCapacity
です)Integer.MAX_VALUE
のでnewCapacity
に本当に近いです。次に、minCapacity
を減算すると、が正の数に戻ってアンダーフローします。
このチェックは、if
が実行されないことを保証します。コードがif (newCapacity < minCapacity)
と書かれていた場合、newCapacity
はoldCapacity
に関係なくminCapacity
に強制されるので、newCapacity
が負であるので、この場合はtrue
となります(newCapacity
が負であるため)。
このオーバーフローのケースは、次のifによって処理されます。 newCapacity
がオーバーフローした場合、true
:MAX_ARRAY_SIZE
はInteger.MAX_VALUE - 8
となり、Integer.MIN_VALUE - (Integer.MAX_VALUE - 8) > 0
はtrue
となります。したがってnewCapacity
は正しく処理されます。hugeCapacity
メソッドはMAX_ARRAY_SIZE
またはInteger.MAX_VALUE
を返します。
NB:これは、この方法のコメントが言っていることです。
コメントに注意してください: '//オーバーフローを意識したコード ' – Tunaki
どのようにオーバーフローを防ぐという点で、 'if(newCapacity - minCapacity)'より 'if(newCapacity - minCapacity <0)'が優れていますか? – Eran
私は、上記の符号のオーバーフローが確かに理由であるかどうか疑問に思います。減算はオーバーフローの可能性が高いようです。コンポーネントはおそらく "これもオーバーフローしません"と言っているかもしれません。両方の変数が非負である可能性があります。 –