Héhé, curieux. Je pense qu'il s'agit d'un "bug intentionnel", pour ainsi dire.
La raison sous-jacente est la façon dont la classe Integer est écrite. En fait, parseInt est "optimisé" pour les nombres positifs. Lorsqu'il analyse la chaîne de caractères, il construit le résultat de manière cumulative, mais avec une négation. Il inverse ensuite le signe du résultat final.
Exemple :
66 = 0x42
analysé comme :
4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)
-64 - 2 = -66 (hex 2 parsed)
return -66 * (-1) = 66
Reprenons maintenant votre exemple FFFF8000
16*(-1) = -16 (first F parsed)
-16*16 = -256
-256 - 16 = -272 (second F parsed)
-272 * 16 = -4352
-4352 - 16 = -4368 (third F parsed)
-4352 * 16 = -69888
-69888 - 16 = -69904 (forth F parsed)
-69904 * 16 = -1118464
-1118464 - 8 = -1118472 (8 parsed)
-1118464 * 16 = -17895552
-17895552 - 0 = -17895552 (first 0 parsed)
Here it blows up since -17895552 < -Integer.MAX_VALUE / 16 (-134217728).
Attempting to execute the next logical step in the chain (-17895552 * 16)
would cause an integer overflow error.
Édition (ajout) : pour que parseInt() fonctionne de manière "cohérente" pour -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, il aurait fallu implémenter une logique de "rotation" lorsqu'on atteint -Integer.MAX_VALUE dans le résultat cumulé, en recommençant à l'extrémité maximale de la plage d'entiers et en continuant vers le bas à partir de là. Il faudrait demander à Josh Bloch ou à la personne qui l'a implémenté en premier lieu pourquoi ils n'ont pas fait cela. Il s'agit peut-être simplement d'une optimisation.
Cependant,
Hex=Integer.toHexString(Integer.MAX_VALUE);
System.out.println(Hex);
System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));
fonctionne très bien, justement pour cette raison. Dans le sourcee pour Integer vous pouvez trouver ce commentaire.
// Accumulating negatively avoids surprises near MAX_VALUE