IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> integer使用==比较大小引发的线上问题记录 -> 正文阅读

[Java知识库]integer使用==比较大小引发的线上问题记录

????记录一个线上反馈出的问题,虽然问题解决了,但是反应出的问题是基本的代码规范问题,希望对遇到此类问题或现在对此问题存在认知误区的同学有所帮助和警示。
????简单描述一下场景:课程需要与会员卡进行关联,课程详情页面需要显示所有的会员卡信息,并将已关联的会员卡进行选中设置。设置是否选中的逻辑是嵌套遍历所有会员卡列表和数据库记录课程已关联的会员卡列表,如果两个会员卡id相同则进行设置选中标识。
????项目中使用的是 == 进行比较两个会员卡id是否相同。项目上线之后运行正常,过一段时间之后反馈出的问题是新增课程关联的会员卡信息时,明明已经勾选会员卡,但是保存成功之后还是显示未选中的状态。
问题定位:
????对于字符串类型的数值比较大部分人都会使用equals,毕竟是比较的是内容非地址值。而==就不一样了,如果是对于基本数据类型,==比较的是数值是否相等非地址值,但是对于包装类型(也属于引用类型)比较的就是地址值。所以这个问题处理方式很简单,第一种方式就是将会员卡的数据类型修改为int(项目中的会员卡id定义的原数据类型为integer),还是使用==进行比较;另一种方式使用equals进行比较(会员卡数据类型不变还是integer)。
????代码验证上面的处理方案:
示例代码:

 public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);  // true
        Integer a1 = 127;
        Integer b1 = 127;
        System.out.println(a1 == b1);  // true
        Integer a2 = 128;
        Integer b2 = 128;
        System.out.println(a2 == b2);  // false
        Integer c = 143;
        Integer d = 143;
        System.out.println(c == d);  // false
        System.out.println(c.equals(d));  // true
        int e = 256;
        int f = 256;
        System.out.println(e == f);   // true
    }

????说一下为什么可以使用equals进行Integer类型比较数值大小:
Integer中equals方法源码:

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

Integer中intValue方法源码:

  public int intValue() {
        return value;
    }

????也就是说Integer中的equals最终还是将Integer转化成int进行比较数值大小。
????继续回答为什么使用==进行数据比较大小,上线一段时间之后才会出现问题。那就要看一下==底层是如何进行实现的。Java是跨平台语言,java代码在任意系统执行流程是先编译成class文件,然后class文件编译成汇编代码,各操作系统底层都是执行的都是汇编指令。那现在使用javap -c命令将class文件反编译成汇编代码。执行之后截图如下:
在这里插入图片描述
????对于integer类型使用==比较大小实际调用了Integer valueOf方法,源码如下:

 public static Integer valueOf(int var0) {
        return var0 >= -128 && var0 <= Integer.IntegerCache.high ? 
        Integer.IntegerCache.cache[var0 + 128] : new Integer(var0);
    }

????就是说如果参数大于等于-128并且小于等于Integer.IntegerCache.high就会从IntegerCache中获取,否则重新创建一个Integer对象。好继续看IntegerCache是什么。

  /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */
 private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

通过源码可知:
???? IntegerCache的最小值low为-128,IntegerCache的最大值high默认为127;通过注释可知high可以通过启动应用程序时加上 -XX:AutoBoxCacheMax=<size> 选项来指定high的值.所以这就说明了对于integer类型的会员卡id使用==进行比较时项目上线没有出现问题,运行一段时间之后才出现问题是因为新增的会员卡id还没超过127.
???? 总结:关于整数类型比较大小,如果数据类型为int,可以使用==进行比较;如果是integer类型,最好还是使用equals进行比较。
???? 有些编码规范平常书写要注意,当然遇到问题处理一次加深一下印象也是好事,不过线上问题犯错的代价不要太大就好。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 11:43:27  更:2022-05-10 11:47:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:36:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码