Java修改Integer变量值遇到的问题及解决

 更新时间:2021年09月17日 17:18:00   作者:丶老邱  
这篇文章主要介绍了Java修改Integer变量值遇到的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Java 修改Integer变量值

对于Integer变量来说,比较变量值常见情形如下:

Integer a = 1000;  
    Integer b = 1000;  
    Integer c = 100;  
    Integer d = 100;  
    System.out.println(a == b);  
    System.out.println(c == d);  

“==”比较的是地址的值,所以正确答案是false,true;

当我们对一个Interger变量直接用“=”号赋值时,相当于自动装箱,即把右边的int型变量(整数时默认是int) 转换成Integer变量,另外我们看看源码

/** 
         * Returns an {@code Integer} instance representing the specified 
         * {@code int} value.  If a new {@code Integer} instance is not 
         * required, this method should generally be used in preference to 
         * the constructor {@link #Integer(int)}, as this method is likely 
         * to yield significantly better space and time performance by 
         * caching frequently requested values. 
         * 
         * This method will always cache values in the range -128 to 127, 
         * inclusive, and may cache other values outside of this range. 
         * 
         * @param  i an {@code int} value. 
         * @return an {@code Integer} instance representing {@code i}. 
         * @since  1.5 
         */  
        public static Integer valueOf(int i) {  
            assert IntegerCache.high >= 127;  
            if (i >= IntegerCache.low && i <= IntegerCache.high)  
                //当为-128和127之间时,并没有new一个Integer,而是从缓存中取  
                return IntegerCache.cache[i + (-IntegerCache.low)];  
            return new Integer(i);  
        }  

所以说如果int的值为-128到127时,是从常量池里取的Integer变量,所以“c==d”是对的,因为c、d是100

而“a==b”为false,因为他们的值为1000,所以是在堆里new出两个不同的变量。

这些都很好理解,但是怎么改变Integer的整型值呢?

我尝试了两种方法去改变Integer的整型值

(1)

有这么一个方法

public void ceshi(Integer integer){
    integer=4444;
}

main方法

Integer shuzi=new Integer(100);
new Test55().ceshi(shuzi);
System.out.println(shuzi);

输出的结果却还是100而不是444

再来看看

(2)

main方法

Integer shuzi=new Integer(100);
shuzi=5000;
System.out.println(shuzi);

这回输出的结果却又是5000,为什么(1)和(2)都用了“=”号赋值,一个成功,一个却失败了?

看看源码

Integer的源码:

/**
 * The value of the {@code Integer}.
 *
 * @serial
 */
private final int value;

Integer变量里的value明明就是final变量,照理说是不能够修改的,那为什么(2)却成功了?

因为:在(2)的这个情况里,我对它赋值5000,相当于new了一个新的Integer变量,它的value值是5000,然后把这个新的变量赋给“shuzi”这个变量,原来那个value值为100的Integer变量就被覆盖了,除非我用一个副本保存,不然他就会被GC清除了。

还有一个问题:那为什么(1)改变不了?

因为:我们先要知道,Java 只有值传递,只不过值传递分为:内存中数值的值传递以及内存地址数值的值传递,传递一个Integer变量参数进去,实际上是构建了一个副本,通过这个副本我们只能去修改原来Integer变量的非final成员变量(假如有的话,也可以是其他类型),上面也说了,如果去修改Integer类型的final变量,那么是会新new一个Integer变量,去覆盖这个变量副本,所以原来的Integer变量还是原来的,仅仅是“ceshi”这个方法里的副本变量变了,这么理解就清楚了。

Integer值比较需要注意的问题

package com.com.test;
 
/**
 * Created by ***** 2018/6/29 9:18
 * java中Integer类型对于-128-127之间的数是缓冲区取的,
 *  所以用等号比较是一致的。但对于不在这区间的数字是在堆中new出来的。所以地址空间不一样,也就不相等。
 */
public class IntegerTest {
    public static void main(String[] args) {
        Integer a1 = Integer.valueOf(60);  //danielinbiti
        Integer b1 = 60;
        System.out.println("1:="+(a1 == b1));  //true
 
 
        Integer a2 = 60;
        Integer b2 = 60;
        System.out.println("2:="+(a2 == b2));   //true
 
 
        Integer a3 = new Integer(60);
        Integer b3 = 60;   // 装箱过程也就是Integer b3=Integer.valueOf(60)
        System.out.println("3:="+(a3 == b3));    //false
//        System.out.println("3:="+(a3.equals(b3)));   //true
 
        Integer a4 = 129;//大于127时,在堆中新建
        Integer b4 = 129;
        System.out.println("4:="+(a4 == b4));  //false
//        System.out.println("4:="+(a4.equals(b4)));    //true
    }
}

代码如上所示,运行结果在注释后。

原因

java中Integer类型对于-128-127之间的数是缓冲区取的,所以用等号比较是一致的。但对于不在这区间的数字是在堆中new出来的。所以地址空间不一样,也就不相等。

Integer b3=60,这是一个装箱过程也就是Integer b3=Integer.valueOf(60)

解决办法

使用 equals 代替 “==“,即是前者可能在性能上稍逊于后者,但是用后者的话存在bug的可能性。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java ThreadLocal 类常用方法源码解析

    java ThreadLocal 类常用方法源码解析

    这篇文章主要为大家介绍了java ThreadLocal类常用方法源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 详解SpringBoot自动配置源码

    详解SpringBoot自动配置源码

    今天带大家来分析SpringBoot自动配置源码,文中有非常详细的代码示例,对正在学习java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-06-06
  • MyBatis实现简单的数据表分月存储

    MyBatis实现简单的数据表分月存储

    本文主要介绍了MyBatis实现简单的数据表分月存储,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 用Java生成二维码并附带文字信息

    用Java生成二维码并附带文字信息

    这篇文章主要介绍了用Java生成二维码并附带文字信息,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • java编程实现两个大数相加代码示例

    java编程实现两个大数相加代码示例

    这篇文章主要介绍了java编程实现两个大数相加代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-12-12
  • 浅谈SpringBoot集成Redis实现缓存处理(Spring AOP实现)

    浅谈SpringBoot集成Redis实现缓存处理(Spring AOP实现)

    这篇文章主要介绍了浅谈SpringBoot集成Redis实现缓存处理(Spring AOP实现),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Springboot中yml对于list列表配置方式详解

    Springboot中yml对于list列表配置方式详解

    这篇文章主要介绍了Springboot中yml对于list列表配置方式详解,使用@ConfigurationProperties读取yml配置文件过程中会遇到读取yml文件中列表,Config里面使用List集合接收,方法比较简单,需要的朋友可以参考下
    2023-11-11
  • springboot中@component注解的使用实例

    springboot中@component注解的使用实例

    这篇文章主要介绍了springboot中@component注解的使用实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Mybatis持久层框架入门之CRUD实例代码详解

    Mybatis持久层框架入门之CRUD实例代码详解

    这篇文章主要介绍了Mybatis持久层框架入门之CRUD实例,需要的朋友可以参考下
    2022-05-05
  • java编程中实现调用js方法分析

    java编程中实现调用js方法分析

    这篇文章主要介绍了java编程中实现调用js方法,结合具体实例形式较为详细的分析了java编程中调用js方法的常用操作技巧与注意事项,需要的朋友可以参考下
    2017-09-09

最新评论