• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

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

java 搞代码 4年前 (2022-01-09) 25次浏览 已收录 0个评论

今天使用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 ? truec == 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对象,所以他们在使用==

本文来源gaodai.ma#com搞#代!码网_

比较的时候,就是相等的(对于对象类型来说,==比较的是两个对象的引用指向堆中的地址) ,而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比较容易犯的错误总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持搞代码

更多细数java中Long与Integer比较容易犯的错误总结相关文章请关注搞代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:细数java中Long与Integer比较容易犯的错误总结

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址