1. ホーム
  2. java

[解決済み] Javaにおけるダブルチルド(~~)の意味を教えてください。

2022-04-19 06:03:03

質問

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;

の両方が adjusthashint s. 私が知っているJavaの知識では ~ はビット単位の否定を意味するので adjust = ~~adjusthash = ~~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;

はコンパイラの警告 "同一の式を比較する" を出力し、これはまさに釘付けになります。

どのように解決するのか?

Javaでは、何の意味もありません。

でも、そのコメントには、JavaをJavaScriptにコンパイルするGWTに特化した行だと書いてあります。

JavaScriptでは、整数は「整数と同じ働きをする倍数」のようなものです。たとえば、最大値は2^53です。しかし ビット演算子 は数字を32ビットとして扱うので、このコードではまさにそれを望んでいるのです。つまり ~~hash というのは hash を32ビットの数値として扱います。具体的には、下位32ビットを除くすべてのビットを破棄します(ビット単位の ~ 演算子は下位32ビットしか見ません)、これはJavaのオーバーフローの仕組みと同じです。

もしそれがなかったら、オブジェクトのハッシュコードは、Javaの国で評価されるか、JavaScriptの国で(GWTコンパイルによって)評価されるかによって違ってきます。