Le mar 9 mars 2010 à 3 h 02, Kevin L. Stern a écrit:
J'ai fait une recherche rapide et il semble que Java soit en effet basé sur le complément à deux. Néanmoins, permettez-moi de souligner que, en général, ce type de code m'inquiète car je m'attends à ce qu'à un moment donné quelqu'un vienne et fasse exactement ce que Dmytro a suggéré; c'est-à-dire que quelqu'un va changer:
if (a - b > 0)
à
if (a > b)
et le navire entier coulera. Personnellement, j'aime éviter les obscurités telles que faire du débordement d'entier une base essentielle pour mon algorithme, sauf s'il y a une bonne raison de le faire. Je préférerais en général éviter tout débordement et rendre le scénario de débordement plus explicite:
if (oldCapacity > RESIZE_OVERFLOW_THRESHOLD) {
// Do something
} else {
// Do something else
}
C'est un bon point.
En ArrayList
nous ne pouvons pas le faire (ou du moins pas de manière compatible), car il
ensureCapacity
s'agit d'une API publique et accepte effectivement déjà les nombres négatifs comme des demandes d'une capacité positive qui ne peuvent pas être satisfaites.
L'API actuelle est utilisée comme ceci:
int newcount = count + len;
ensureCapacity(newcount);
Si vous voulez éviter le débordement, vous devrez changer pour quelque chose de moins naturel comme
ensureCapacity(count, len);
int newcount = count + len;
Quoi qu'il en soit, je garde le code conscient des débordements, mais j'ajoute plus de commentaires d'avertissement et je «souligne» la création de tableaux énormes pour que
ArrayList
le code ressemble maintenant à:
/**
* 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 s'est régénéré.
Martin
if (newCapacity - minCapacity < 0)
mieux qu'enif (newCapacity < minCapacity)
termes de prévention des débordements?