boxed Long 값 127과 128 비교


111

조건을 사용하여 두 개의 Long 개체 값 을 비교하고 싶습니다 if. 이 값은 때 적은 128보다if조건은 제대로 작동하지만,이 경우 보다 크거나 128에 동일 비교는 실패합니다.

예:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

위 코드의 비교는 제대로 작동하지만 아래 코드에서는 실패합니다.

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

Long 변수를 127보다 큰 값과 비교할 때 왜 문제가 있습니까? 변수 데이터 유형이 long primitives 로 변경 되면 비교가 모든 경우에 적용됩니다.

답변:


212

TL; DR

Java는 boxed Integer 인스턴스를 -128에서 127. 대신 ==객체 참조 를 비교 하는 데 사용 하고 있으므로 캐시 된 객체 만 일치합니다. 박스되지 않은 기본 값으로 작업 하거나 객체 를 비교 하는 데 사용하십시오 .long.equals()Long

긴 (말장난 의도) 버전

Long 변수를 127보다 큰 값과 비교하는데 왜 문제가 있습니까? 위 변수의 데이터 유형이 원시 (long)이면 모든 값에 대해 코드가 작동합니다.

Java는 -128 ~ 127 범위의 Integer 개체 인스턴스를 캐시합니다 . 즉,

  • N Long 변수 값 127( cached )으로 설정하면 모든 참조가 동일한 객체 인스턴스를 가리 킵니다. (N 변수, 1 인스턴스)
  • N Long 변수로 값을 설정하면 128( 캐시되지 않음 ), 모든 참조가 가리키는 객체 인스턴스를 갖게됩니다. (N 변수, N 인스턴스)

그 이유는 다음과 같습니다.

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2);

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4);

다음을 출력합니다.


거짓

를 들어 127L의 메모리 (캐시)에 동일한 개체 인스턴스를 모두 참조 (VAL1과 val2만큼) 포인트 이후 값, 그것은 반환합니다 true.

한편,에 대한 (128) 메모리에 캐쉬 그것을위한 인스턴스가 없기 때문에 값, 새로운 하나 (val3 및 val4 가리키는) 두 가지 경우에 생성 및 리턴 박스형 값에 대한 새로운 할당을 위해 만들어 false온 그들 사이의 비교.

이는 기본 값이 아닌 두 개의 Long 객체 참조를 연산자 long와 비교하기 때문에 발생합니다 ==. 이 캐시 메커니즘이 아니라면 이러한 비교는 항상 실패하므로 여기서 실제 문제는 박스형 값을 ==연산자 와 비교하는 것 입니다.

이러한 변수를 기본 long유형으로 변경하면 이런 일이 발생하지 않지만 Long객체를 사용하여 코드를 유지해야하는 경우 다음 접근 방식으로 이러한 비교를 안전하게 수행 할 수 있습니다.

System.out.println(val3.equals(val4));                     // true
System.out.println(val3.longValue() == val4.longValue());  // true
System.out.println((long)val3 == (long)val4);              // true

(캐스트에도 적절한 null 검사 필요)

IMO , 객체 비교를 처리 할 때 항상 .equals () 메서드 를 사용하는 것이 좋습니다 .

참조 링크 :


15

Java는 -128에서 127 까지의 기본 값을 캐시합니다 . 두 개의 Long 객체를 비교할 때 java는 내부적으로 원시 값으로 형변환하고 비교합니다. 그러나 127 이상에서는 Long 객체가 유형 카스트를 얻지 못합니다. Java는 .valueOf () 메소드로 출력을 캐시합니다 .

이 캐싱은 -128에서 127까지 Byte, Short, Long에 대해 작동합니다. Integer 캐싱의 경우 -128에서 java.lang.Integer.IntegerCache.high 또는 127 중 더 큰 값으로 작동합니다. (우리는 Integer 값까지 최상위 값을 설정할 수 있습니다. java.lang.Integer.IntegerCache.high를 사용하여 캐시되어야합니다).

 For example:
    If we set java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

Float 및 Double 개체는 캐시되지 않습니다.

캐릭터는 0에서 127까지 캐시를 얻습니다.

두 개체를 비교하고 있습니다. 그래서 == 연산자는 객체 참조의 동일성을 확인합니다. 이를 수행하는 방법은 다음과 같습니다.

1) 두 객체를 모두 원시 값으로 유형 캐스팅하고 비교

    (long)val3 == (long)val4

2) 객체의 값을 읽고 비교

    val3.longValue() == val4.longValue()

3) 객체 비교시 equals () 메소드를 사용합니다.

    val3.equals(val4);  

14

num1그리고 num2Long 객체입니다. equals()그것들을 비교하기 위해 사용해야 합니다. ==JVM 상자 기본 형식으로 인해 비교가 때때로 작동 할 수 있지만 이에 의존하지 마십시오.

if (num1.equals(num1))
{
 //code
}

1
이것은 (더 낫다) 또는의 반환 값을 비교합니다 .longValue().
Giulio Franco

4

Java에서 비 기본 요소 (일명 객체)를 ==비교하면 해당 값 대신 참조 를 비교합니다. Long클래스이므로 Long값은 객체입니다.

문제는 자바 개발자는 사람들이 사용하고 싶어한다는 것입니다 Long그들이 예전처럼 long것으로, 본질적 기능입니다 오토 박싱의 개념을 주도 호환성을 제공하는 long-values가 변경됩니다 Long-Objects 그 반대는 반대로했습니다. 오토 박싱의 동작은 완전히 지정되지 않았기 때문에 항상 정확하게 예측할 수는 없습니다.

따라서 안전하고 예측 가능한 결과를 얻으려면 항상 .equals()개체를 비교 하는 데 사용 하고이 경우 오토 박싱에 의존하지 마십시오.

Long num1 = 127, num2 = 127;
if(num1.equals(num2)) { iWillBeExecutedAlways(); }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.