При просмотре исходного кода гуавы, я наткнулся на следующий фрагмент кода (часть реализации hashCode
для внутреннего класса CartesianSet
):В чем смысл двойной тильды (~~) в Java?
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
и hash
являются int
s. Из того, что я знаю о Java, ~
означает побитовое отрицание, поэтому adjust = ~~adjust
и hash = ~~hash
должны оставить переменные неизменными. Выполнение небольшого теста (с учетом утверждений, конечно),
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
подтверждает это. Предполагая, что ребята из Guava знают, что они делают, для этого должна быть причина. Вопрос в том, что?
EDIT Как было отмечено в комментариях выше тест не включает в себя случай, когда i
приравнивает Integer.MAX_VALUE
. Поскольку i <= Integer.MAX_VALUE
всегда истинно, нам нужно будет проверить этот случай вне цикла, чтобы он не зацикливался навсегда. Однако линия
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
дает предупреждение о компиляторе «Сравнение идентичных выражений», что в значительной степени прибивает его.
@dr_andonuts Guava - довольно стандартная библиотека для включения в проект в наши дни - я думаю, что совет, чтобы бежать далеко, неуместен. – yshavit
Утверждение не проверяет кромку края 'Integer.MAX_VALUE'. Контраст с '- (- Integer.MIN_VALUE)! = Integer.MIN_VALUE'. – Franky
@Franky. Вы правы с отсутствующим тестовым примером, но неправильно с другой частью, как и для каждого 'int', как' - (- x) ', так и' ~ (~ x) 'equal' x', независимо от того, что , – maaartinus