>Java >java지도 시간 >Java에서 Long과 Integer 사이의 일반적인 실수에 대한 자세한 요약

Java에서 Long과 Integer 사이의 일반적인 실수에 대한 자세한 요약

高洛峰
高洛峰원래의
2017-01-22 10:22:231413검색

오늘 findbug를 사용하여 프로젝트를 스캔한 결과, 가장 일반적인 취약점 중 하나는 두 개의 Long 또는 Integer를 비교할 때 ==를 직접 사용하는 것입니다. 사실 이것은 잘못된 것입니다.

Long과 Ineger는 포장의 종류이자 오브제이기 때문입니다. 일반 유형인 long 및 int 대신 비교할 때 같음을 사용해야 하거나 먼저 longValue() 또는 intValue() 메서드를 사용하여 기본 유형 값을 가져온 다음 ==를 사용하여 비교할 수 있습니다.

그러나 실제로는 Long 및 Integer 캐시 개체 모두 -128~127인 특별한 경우가 있습니다. Long 유형의 소스 코드에 LongCache 클래스가 있음을 알 수 있습니다. 코드는 다음과 같습니다.

private static class LongCache {
 private LongCache(){}
 
 static final Long cache[] = new Long[-(-128) + 127 + 1];
 
 static {
   for(int i = 0; i < cache.length; i++)
 cache[i] = new Long(i - 128);
 }
  }

먼저 이 예제를 살펴보겠습니다.

public class Test05 {
 
  public static void main(String[] args) {
    Long a = 5L;
    Long b = 5L;
 
    System.out.println("a == b ? " + (a == b));
 
    Long c = 129L;
    Long d = 129L;
    System.out.println("c == d ? " + (c == d));
  }
}

인쇄된 결과는 다음과 같습니다.

a == b ? true
c == d ? false

Cause

먼저 Long a = 5L; 기본 유형을 Long 객체로 래핑하는 방법을 살펴보겠습니다.

테스트 클래스를 작성한 후 디컴파일하여 Java가 Long a = 5L과 같은 명령을 어떻게 구문 분석하는지 확인할 수 있습니다.

테스트 클래스는 다음과 같습니다.

public class Test06 {
  Long l = 3L;
}

그런 다음 javap -verbose Test06을 사용하여 디컴파일 결과를 확인합니다.

{
java.lang.Long l;
 
public com.spring.test.Test06();
 Code:
  Stack=3, Locals=1, Args_size=1
  0:  aload_0
  1:  invokespecial  #10; //Method java/lang/Object."<init>":()V
  4:  aload_0
  5:  ldc2_w #12; //long 3l
  8:  invokestatic  #14; //Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
  11: putfield    #20; //Field l:Ljava/lang/Long;
  14: return
 LineNumberTable:
  line 3: 0
  line 5: 4
  line 3: 14
 
 LocalVariableTable:
  Start Length Slot Name  Signature
  0   15   0  this    Lcom/spring/test/Test06;
 
 
}

Code의 8에서 Long의 클래스 메소드 Long.valueOf(Long)가 호출되는 것을 볼 수 있으므로 Long a = 5L이라는 결론을 내릴 수 있습니다. 실제로 Long a = Long.valueOf(5) ;

그런 다음 Long.valueOf() 메서드가 어떻게 정의되어 있는지 살펴보세요.

public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
  return LongCache.cache[(int)l + offset];
}
   return new Long(l);
 }


기본 유형의 값이 -128~127 사이이면 캐시된 객체를 LongCache에서 직접 가져와 반환하고, 그렇지 않으면 새로운 Long 객체를 반환한다는 것을 한눈에 알 수 있습니다.

이제 Test05 프로그램 실행 결과를 이해하는 것은 어렵지 않습니다. 왜냐하면 a와 b는 -127~128 범위 내에서 5이므로 둘 다 LongCache에서 직접 반환된 Long 개체이므로 ==를 사용하여 비교하면 동일하며(객체 유형의 경우 ==는 두 객체의 참조가 가리키는 힙의 주소를 비교함) c와 d는 -127~128 사이가 아니라 129와 같습니다. 따라서 별도로 생성된 두 개의 새로운 Long 객체이므로 ==를 사용하여 비교하면 동일하지 않습니다.

Long은 equals 메소드를 대체합니다.

public boolean equals(Object obj) {
 if (obj instanceof Long) {
   return value == ((Long)obj).longValue();
 }
 return false;
  }

먼저 .longValue() 메소드를 통해 Long 객체의 기본 유형 long 값을 얻은 후 비교합니다. .

따라서 Integer와 Long을 비교할 때는 원하는 결과를 얻으려면 같음을 사용하는 것이 가장 좋습니다.

Integer는 Long과 동일하므로 여기서는 예시를 생략하겠습니다.

위의 Java에서 Long 및 Integer의 일반적인 실수에 대한 요약은 모두 편집자가 공유한 내용이므로 참고가 되기를 바라며, 또한 모든 분들이 PHP 중국어 웹사이트를 지원해 주시길 바랍니다.

Java에서 Long과 Integer가 범하는 일반적인 실수에 대한 자세한 요약을 보려면 PHP 중국어 웹사이트를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.