Під час перегляду вихідного коду Guava я натрапив на такий фрагмент коду (частина реалізації hashCode
для внутрішнього класу 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
і hash
є int
с. З того, що я знаю про Java, ~
означає побітове заперечення, тому adjust = ~~adjust
і hash = ~~hash
слід залишати змінні незмінними. Запустивши невеликий тест (звичайно з увімкненими твердженнями),
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
це підтверджує. Якщо припустити, що хлопці з Гуави знають, що вони роблять, у них повинна бути причина. Питання - що?
EDIT Як зазначено в коментарях, тест, зазначений вище, не включає випадок, коли i
дорівнює Integer.MAX_VALUE
. Оскільки i <= Integer.MAX_VALUE
це завжди вірно, нам потрібно буде перевірити цей випадок за межами циклу, щоб не допустити його циклу назавжди. Однак лінія
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
дає попередження компілятора "Порівняння однакових виразів", що в значній мірі нівелює.
Integer.MAX_VALUE
. Контраст с -(-Integer.MIN_VALUE) != Integer.MIN_VALUE
.
-Integer.MIN_VALUE
обгортає Integer.MIN_VALUE
, настільки заперечуючи, що знову просто Integer.MIN_VALUE
знову створюється .
-x = (~x) + 1
.