Martedì 9 marzo 2010 alle 03:02, Kevin L. Stern ha scritto:
Ho fatto una ricerca veloce e sembra che Java sia davvero basato sul complemento di due. Tuttavia, mi permetta di sottolineare che, in generale, questo tipo di codice mi preoccupa poiché mi aspetto pienamente che a un certo punto qualcuno verrà e farà esattamente ciò che Dmytro ha suggerito; cioè qualcuno cambierà:
if (a - b > 0)
per
if (a > b)
e l'intera nave affonderà. Personalmente, mi piace evitare oscurità come rendere il trabocco di numeri interi una base essenziale per il mio algoritmo, a meno che non ci siano buone ragioni per farlo. In generale, preferirei evitare del tutto l'overflow e rendere più esplicito lo scenario di overflow:
if (oldCapacity > RESIZE_OVERFLOW_THRESHOLD) {
// Do something
} else {
// Do something else
}
È un buon punto.
In ArrayList
non possiamo farlo (o almeno non in modo compatibile), perché
ensureCapacity
è un'API pubblica e accetta effettivamente numeri negativi come richieste per una capacità positiva che non può essere soddisfatta.
L'API corrente viene utilizzata in questo modo:
int newcount = count + len;
ensureCapacity(newcount);
Se si desidera evitare il trabocco, è necessario passare a qualcosa di meno naturale
ensureCapacity(count, len);
int newcount = count + len;
Ad ogni modo, sto mantenendo il codice attento all'overflow, ma aggiungendo altri commenti di avvertimento e "creando" un'enorme creazione di array in modo che
ArrayList
il codice ora assomigli a:
/**
* 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 rigenerato.
balestruccio
if (newCapacity - minCapacity < 0)
meglio cheif (newCapacity < minCapacity)
in termini di prevenzione del trabocco?