Pada Selasa, 9 Maret 2010 pukul 03:02, Kevin L. Stern menulis:
Saya melakukan pencarian cepat dan tampaknya Java memang berdasarkan dua komplemen. Meskipun demikian, izinkan saya menunjukkan bahwa, secara umum, jenis kode ini membuat saya khawatir karena saya sepenuhnya berharap bahwa pada suatu saat seseorang akan datang dan melakukan persis seperti yang disarankan Dmytro; yaitu seseorang akan berubah:
if (a - b > 0)
untuk
if (a > b)
dan seluruh kapal akan tenggelam. Saya, secara pribadi, ingin menghindari ketidakjelasan seperti membuat integer overflow sebagai dasar penting untuk algoritme saya kecuali ada alasan bagus untuk melakukannya. Secara umum, saya lebih suka untuk menghindari overflow sama sekali dan membuat skenario overflow lebih eksplisit:
if (oldCapacity > RESIZE_OVERFLOW_THRESHOLD) {
// Do something
} else {
// Do something else
}
Ini poin yang bagus.
Di ArrayList
kita tidak dapat melakukan ini (atau setidaknya tidak kompatibel), karena
ensureCapacity
merupakan API publik dan secara efektif sudah menerima angka negatif sebagai permintaan kapasitas positif yang tidak dapat dipenuhi.
API saat ini digunakan seperti ini:
int newcount = count + len;
ensureCapacity(newcount);
Jika Anda ingin menghindari overflow, Anda perlu mengubah sesuatu yang kurang alami
ensureCapacity(count, len);
int newcount = count + len;
Pokoknya, saya menjaga kode overflow-aware, tetapi menambahkan lebih banyak komentar peringatan, dan "out-lining" pembuatan array besar sehingga
ArrayList
kode sekarang terlihat seperti:
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
modCount++;
// Overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// Overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
private int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
Webrev dibuat ulang.
Martin
if (newCapacity - minCapacity < 0)
lebih baik daripadaif (newCapacity < minCapacity)
dalam hal mencegah overflow?