当前位置: 移动技术网 > IT编程>开发语言>Java > 细数java中Long与Integer比较容易犯的错误总结

细数java中Long与Integer比较容易犯的错误总结

2019年07月22日  | 移动技术网IT编程  | 我要评论

今天使用findbugs扫描项目后发现很多高危漏洞,其中非常常见的一个是比较两个long或integer时直接使用的==来比较。 其实这样是错误的。

因为long与ineger都是包装类型,是对象。 而不是普通类型long与int , 所以它们在比较时必须都应该用equals,或者先使用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


原因

首先来看看 long a = 5l ; 它是如何将一个基本类型long包装成一个对象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里面取出缓存的对象返回,否则就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一样,这里就不举例了。

以上这篇细数java中long与integer比较容易犯的错误总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网