Java에서 이중 물결표 (~~)의 의미는 무엇입니까?


192

구아바의 소스 코드를 탐색 할 때 다음 코드 조각 ( 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들. 나는 자바에 대해 무엇을 알고에서 ~부정 비트 수단, 그렇게 adjust = ~~adjust하고 hash = ~~hash변경되지 않은 변수를 떠나야한다. 작은 테스트 (어설 션이 활성화 된 상태에서) 실행

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

이것을 확인합니다. 구아바 사람들이 그들이하고있는 일을 알고 있다고 가정하면, 그들이해야 할 이유가 있어야합니다. 문제는 무엇입니까?

편집 주석에서 지적했듯이 위의 테스트에는 iequals가 포함되지 않습니다 Integer.MAX_VALUE. i <= Integer.MAX_VALUE항상 참 이므로 루프 외부에서 해당 케이스를 확인하여 루프가 영원히 반복되지 않도록해야합니다. 그러나 라인

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

컴파일러에 "동일한 표현식 비교"라는 경고 메시지가 표시됩니다.


42
@dr_andonuts Guava는 요즘 프로젝트에 포함시킬 꽤 표준적인 라이브러리입니다.
yshavit

4
Asser는 Edge Case를 확인하지 않습니다 Integer.MAX_VALUE. 와 대조하십시오 -(-Integer.MIN_VALUE) != Integer.MIN_VALUE.
Franky

3
@Franky maaartinus가 말한 내용. -Integer.MIN_VALUE로 감싸서 Integer.MIN_VALUE다시 부정하면 다시 생성 Integer.MIN_VALUE됩니다.

2
@maaartinus, @hvd, 지적 해 주셔서 감사합니다. 이제는 기억합니다 -x = (~x) + 1.
Franky

7
@dr_andonuts 트롤링? 왜 당신이 이해하지 못하는 것들을 피하십시오. 이것이 바로 배우기위한 StackOverflow입니다.
Jared Burrows

답변:


245

Java에서는 아무 의미가 없습니다.

그러나 그 의견은 GWT 전용 라인이며 Java에서 JavaScript로 컴파일하는 방법이라고 말합니다.

자바 스크립트에서 정수는 정수처럼 작용합니다. 예를 들어 최대 값은 2 ^ 53입니다. 그러나 비트 연산자 는 숫자를 32 비트 인 것처럼 취급하는데, 이는이 코드에서 원하는 것입니다. 다시 말해, ~~hash"치료하다"hash JavaScript에서 "32 비트 숫자로 . 특히, 비트 ~연산자는 하위 32 비트 만 보이 므로 하위 32 비트를 제외한 모든 비트를 버립니다 . 이는 Java의 오버플로 작동 방식과 동일합니다.

그것을 가지고 있지 않다면 객체의 해시 코드는 Java 랜드 또는 JavaScript 랜드 (GWT 컴파일을 통해)에서 평가되는지에 따라 달라집니다.


10
@harold GWT가 아니며 JavaScript입니다. 이제는 그 언어로 숫자가 작동합니다.
yshavit

18
@yshavit 그러나 Java에서 숫자가 작동하는 방식 은 아닙니다 . GWT가 숫자가 JS와 JVM에서 사용자와 다르게 구현된다는 사실을 숨기지 않으면 실제로 컴파일러가 좋지 않습니다.
valderman

8
@harold, 그렇습니다. 정수를 잘못 구현하는 것은 JavaScript입니다 (실제로는 JavaScript에는 정수 유형과 같은 것이 없습니다).
MikeTheLiar

8
@valderman 좋은 지적입니다. 성능에 어떤 영향을 줄지 모르겠지만 (또는 모든 표현의 모든 단계에서 추가해야 할 것 같지만) |0또는 ~~소리를 추가하는 것은 어렵지 않습니다. 디자인 고려 사항이 무엇인지 모르겠습니다. FWOW의 불일치는 GWT의 호환성 페이지에 설명되어 있습니다.
yshavit

6
hashCode고의적으로 법원에 넘겨 지거나 심지어 오버플로가 발생할 것으로 예상 한다는 점에서 이상 합니다. 불일치를 관찰 할 수있는 유일한 곳은 일반적인 Java int가 오버 플로우되는 곳이며, 이는 대부분의 코드에서 발생하는 문제가 아닙니다. 이 이상한 사건과 관련이 있습니다.
Louis Wasserman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.