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


192

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;

両方adjusthashしているintの。私は、Java、について知っていることから、~否定ビット単位手段、そうadjust = ~~adjusthash = ~~hash変わらない変数を残す必要があります。小さなテストを実行します(もちろん、アサーションを有効にして)、

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

これを確認します。グアバの連中が彼らが何をしているか知っていると仮定すると、彼らがこれをする理由があるに違いない。問題は何ですか?

編集コメントで指摘されているように、上記のテストにはがi等しい場合は含まれていませんInteger.MAX_VALUE。以来i <= Integer.MAX_VALUE、常に真実である、私たちは永遠にループするからそれを防ぐために、ループの外にそのような場合を確認する必要があります。ただし、行

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

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


42
@dr_andonuts Guavaは、最近のプロジェクトに含めるかなり標準的なライブラリです。遠くに走るというアドバイスは見当違いです。
yshavit 2015

4
アサートは、エッジケースをチェックしませんInteger.MAX_VALUE。と対比-(-Integer.MIN_VALUE) != Integer.MIN_VALUE
フランキー、

3
@フランキーmaaartinusが言ったこと。-Integer.MIN_VALUEにラップアラウンドするInteger.MIN_VALUEので、それを否定すると、単にInteger.MIN_VALUE再び生成されます。

2
@ maaartinus、@ hvd、指摘してくれてありがとう。今覚えてい-x = (~x) + 1ます。
フランキー、

7
@dr_andonutsトローリング?なぜあなたが理解していないものから逃げるのですか?これがStackOverflowの目的です。学習に役立ちます。
Jared Burrows、

回答:


245

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

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

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

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


10
@harold GWTではなく、JavaScriptです。それはちょうど今その数はその言語で機能します。
yshavit 2015

18
@yshavitはしかし、それはない数字がJavaでどのように働きますか。GWTがJSとJVMで数値が異なる方法で実装されているという事実をユーザーから隠さない場合、それは確かに貧弱なコンパイラーです。
valderman、2015

8
@harold、そうです、整数を正しく実装しないのはJavaScriptです(JavaScriptには整数型などは実際にはありません)。
MikeTheLiar

8
@valdermanそれは良い点です。|0またはの~~ようなサウンドを追加することは難しくありませんが、パフォーマンスヒットがどうなるかわかりません(すべての式のすべてのステップで追加する必要があります)。どのような設計上の考慮事項があったのかわかりません。Fwiw、不整合はGWTの互換性ページに記載されています
yshavit 2015

6
hashCode意図的にオーバーフローが発生することを意図して、または予想さえして、奇妙です。一貫性がないことを確認できる唯一の場所は、通常のJava intがオーバーフローする場所です。これは、ほとんどのコードで発生する問題ではありません。これは、この1つの奇妙なケースにのみ関連しています。
Louis Wasserman、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.