En parcourant le code source de Guava, je suis tombé sur le morceau de code suivant (faisant partie de la mise en oeuvre de hashCode
pour la classe interne CartesianSet
):
int adjust = size() - 1;
for (int i = 0; i < axes.size(); i++) {
adjust *= 31;
adjust = ~~adjust;
// in GWT, we have to deal with integer overflow carefully
}
int hash = 1;
for (Set<E> axis : axes) {
hash = 31 * hash + (size() / axis.size() * axis.hashCode());
hash = ~~hash;
}
hash += adjust;
return ~~hash;
adjust
et hash
sont tous deux int
s. D'après ce que je sais de Java, ~
signifie négation au niveau du bit, donc adjust = ~~adjust
et hash = ~~hash
devrait laisser les variables inchangées. Lancer le petit test (avec les assertions activées, bien sûr),
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
confirme cela. En supposant que les gars de goyave savent ce qu'ils font, il doit y avoir une raison pour qu'ils le fassent. La question est quoi?
EDIT Comme indiqué dans les commentaires, le test ci-dessus n'inclut pas le cas où i
est égal à Integer.MAX_VALUE
. Puisque i <= Integer.MAX_VALUE
est toujours vrai, nous devrons vérifier que la casse est en dehors de la boucle pour l’empêcher de boucler indéfiniment. Cependant, la ligne
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
donne l’avertissement du compilateur "Comparaison d’expressions identiques", qui le cloue à peu près.
En Java, cela ne signifie rien.
Mais ce commentaire indique que la ligne est spécifiquement pour GWT, ce qui est un moyen de compiler Java en JavaScript.
En JavaScript, les entiers sont un peu comme les doubles-that-act-as-integers. Ils ont une valeur maximale de 2 ^ 53, par exemple. Mais opérateurs au niveau des bits traitons les nombres comme s'ils étaient 32 bits, ce qui est exactement ce que vous voulez dans ce code. En d'autres termes, ~~hash
dit "traite hash
comme un nombre 32 bits" en JavaScript. Plus précisément, il supprime tous les 32 bits inférieurs (depuis le bitwise ~
opérateurs ne regarde que les 32 bits du bas), ce qui est identique au fonctionnement du débordement de Java.
Si vous ne l'aviez pas, le code de hachage de l'objet serait différent selon qu'il est évalué en Java-land ou en JavaScript (via une compilation GWT).