web-dev-qa-db-ja.com

Javaでの二重チルダ(~~)の意味は何ですか?

Guavaのソースコードを参照すると、次のコード(内部クラスhashCodeCartesianSetの実装の一部)に遭遇しました。

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;

adjusthashは両方ともintsです。私がJavaについて知っていることから、~はビットごとの否定を意味するので、adjust = ~~adjusthash = ~~hashは変数を変更しないでください。小さなテストを実行します(もちろん、アサーションを有効にして)。

for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
    assert i == ~~i;
}

これを確認します。グアバの人々が彼らが何をしているかを知っていると仮定すると、彼らがこれをする理由がなければなりません。質問は何ですか?

EDITコメントで指摘したように、上記のテストにはiInteger.MAX_VALUEと等しい場合は含まれません。 i <= Integer.MAX_VALUEは常にtrueであるため、そのケースをループ外でチェックして、永久にループしないようにする必要があります。ただし、行

assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;

コンパイラ警告「同一の式の比較」を生成します。

192
Halle Knast

Javaでは、何も意味しません。

しかし、そのコメントは、この行はGWT専用であり、JavaをJavaScriptにコンパイルする方法だと述べています。

JavaScriptでは、整数はdouble-that-act-as-integersのようなものです。たとえば、最大値は2 ^ 53です。しかし、 ビットごとの演算子 は、32ビットであるかのように数値を処理します。これはまさにこのコードで必要なものです。つまり、~~hashは、JavaScriptで「hashを32ビット数として扱う」と言います。具体的には、下位32ビットを除くすべてを破棄します(ビット単位の~演算子は下位32ビットのみを参照するため)。これは、Javaのオーバーフローの仕組みと同じです。

それがない場合、オブジェクトのハッシュコードは、Javaランドで評価されるかJavaScriptランドで評価されるかによって異なります(GWTコンパイルを介して)。

244
yshavit