Java Integer的值真的能改变么

417 阅读3分钟

对于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)都用了“=”号赋值,一个成功,一个却失败了?

3. 原因查找

Integer的源码:

/**

  • The value of the {@code Integer}.
  • @serial */

private final int value;

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

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

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

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