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

 更新时间:2017年01月22日 10:02:14   投稿:jingxian  
下面小编就为大家带来一篇细数java中Long与Integer比较容易犯的错误总结。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

今天使用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比较容易犯的错误总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java版仿QQ验证码风格图片验证码

    Java版仿QQ验证码风格图片验证码

    这篇文章主要为大家分享了java图片验证码实例代码,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • java实现钉钉机器人消息推送的示例代码

    java实现钉钉机器人消息推送的示例代码

    这篇文章主要介绍了java实现钉钉机器人消息推送的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • Java中Spring扩展点详解

    Java中Spring扩展点详解

    这篇文章主要介绍了Java中Spring技巧之扩展点的应用,下文Spring容器的启动流程图展开其内容的相关资料,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • @Conditional注解的使用场景和源码解析

    @Conditional注解的使用场景和源码解析

    这篇文章主要介绍了@Conditional注解的使用场景和源码解析,@Conditional是一个条件注解,它的作用是判断Bean是否满足条件,如果满足条件,则将Bean注册进IOC中,如果不满足条件,则不进行注册,需要的朋友可以参考下
    2023-11-11
  • 6种SpringBoot中自定义starter的方式介绍

    6种SpringBoot中自定义starter的方式介绍

    在SpringBoot生态中,starter是一种特殊的依赖,它能够自动装配相关组件,简化项目配置,本文将详细介绍6种不同的自定义starter开发方法,有需要的可以了解下
    2025-04-04
  • SpringMVC之简单的增删改查示例(SSM整合)

    SpringMVC之简单的增删改查示例(SSM整合)

    本篇文章主要介绍了SpringMVC之简单的增删改查示例(SSM整合),这个例子是基于SpringMVC+Spring+Mybatis实现的。有兴趣的可以了解一下。
    2017-03-03
  • SpringBoot指标监控的实现

    SpringBoot指标监控的实现

    本文主要介绍了SpringBoot指标监控的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • SpringBoot实现多租户架构

    SpringBoot实现多租户架构

    在SpringBoot中可以通过多数据源和动态路由来实现多租户机制,本文主要介绍了SpringBoot实现多租户架构,具有一定的参考价值,感兴趣的可以里哦啊接一下
    2024-03-03
  • Java JDK11的下载与安装教程

    Java JDK11的下载与安装教程

    这篇文章主要介绍了Java JDK11的下载与安装,本文以win10为例给大家讲解win10系统下载安装jdk11的教程,需要的朋友可以参考下
    2023-05-05
  • SpringBoot的ResponseEntity类返回给前端具体讲解

    SpringBoot的ResponseEntity类返回给前端具体讲解

    这篇文章主要给大家介绍了关于SpringBoot的ResponseEntity类返回给前端的相关资料,ResponseEntity是Spring框架中用于封装HTTP响应的类,可以自定义状态码、响应头和响应体,常用于控制器方法中返回特定数据的HTTP响应,需要的朋友可以参考下
    2024-11-11

最新评论