web-dev-qa-db-fra.com

Quelle est la signification de double tilde (~~) en Java?

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 ints. 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.

192
Halle Knast

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).

244
yshavit