자바에서 Long과 Integer가 범하기 쉬운 오류 요약

3429 단어 javalonginteger
오늘 findbugs를 사용하여 프로젝트를 스캔한 후에 매우 많은 고위험 빈틈을 발견했습니다. 그 중에서 매우 흔히 볼 수 있는 것은 두 개의 Long이나 Integer를 비교할 때 직접 사용하는 ==를 비교합니다.사실 이렇게 하는 것은 잘못된 것이다.
Long과 Ineger는 모두 포장 유형이고 대상이기 때문이다.일반 형식인 롱과 int가 아니기 때문에 비교할 때 반드시 equals를 사용하거나 롱밸류 () 또는 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


원인
우선 Long a = 5L 살펴보겠습니다.그것은 어떻게 하나의 기본 유형인 롱을 하나의 대상인 롱으로 포장하는가.
테스트 클래스를 작성하고 역컴파일해서 자바가 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;


}

코드의 8에서 Long의 한 가지 방법을 사용한 것을 알 수 있다. Long.valueOf(Long), 그래서 얻을 수 있는 결론은 Long a = 5L은 실제로는 Long a = Long과 같다.valueOf(5) ;
그리고 롱을 보자.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에서 캐시를 꺼낸 대상을 되돌려주고 그렇지 않으면 new에서 새로운 Long 대상을 되돌려줍니다.
이제 Test05 프로그램이 실행한 결과를 이해하기 어렵지 않다. a와 b는 5이고 -127~128 이내이기 때문에 모두 LongCache에서 직접 되돌아오는 Long 대상이기 때문에 그들은 ==를 비교할 때 서로 같다(대상 유형에 있어 == 비교는 두 대상의 인용이 무더기에 있는 주소를 가리킨다). 반면에 c와 d는 129이고 -127~128 사이가 아니다.그래서 그들은 각각 new에서 나온 두 개의 새로운 Long 대상으로 ==를 사용하면 자연히 서로 같지 않다.
Long은 equals 방법을 다시 썼습니다.

public boolean equals(Object obj) {
 if (obj instanceof Long) {
   return value == ((Long)obj).longValue();
 }
 return false;
  }
그것은 먼저 통과했다.longValue () 방법은 Long 대상의 기본 유형인 long의 값을 가져와서 비교합니다.
따라서 Integer와 Long의 비교는 equals를 사용해야 우리가 원하는 결과를 얻을 수 있다.
Integer는 Long과 마찬가지로 예를 들지 않습니다.
이상의 자바에서 Long과 Integer가 범하기 쉬운 오류를 요약한 것은 바로 편집자가 여러분에게 공유한 모든 내용입니다. 여러분께 참고가 되고 저희를 많이 사랑해 주시기 바랍니다.

좋은 웹페이지 즐겨찾기