欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

工作中Integer类型传参遇到的陷阱

程序员文章站 2024-02-14 15:05:58
...

遇到的问题

//i = 0
Integer integer=new new Integer(i); 
//i改成4
tempList = this.commonCalMainProcess(list,indexList,integer,position,null); 
//i还是等于0
i = integer;

误区:传对象传的就是地址的引用,所以改变integer的值,它的指向的值也会跟着改变。

一个单元测试

@Test
    public void test02(){
        Integer a1 = Integer.valueOf(60);
        Integer b1 = 60;
        System.out.println(System.identityHashCode(a1));
        System.out.println(System.identityHashCode(b1));
        System.out.println("1:"+(a1 == b1));
        System.out.println("------------------");
        Integer a2 = 60;
        Integer b2 = 60;
        System.out.println(System.identityHashCode(a2));
        System.out.println(System.identityHashCode(b2));
        System.out.println("2:"+(a2 == b2));
        System.out.println("------------------");
        Integer a3 = new Integer(60);       //a3--->堆里的地址,常量池中也会有一个60
        Integer b3 = 60;                          //b3---->常量池中的60
        System.out.println(System.identityHashCode(a3));
        System.out.println(System.identityHashCode(b3));
        System.out.println("3:"+(a3 == b3));
        System.out.println("------------------");
        Integer a4 = 127;
        Integer b4 = 127;
        System.out.println(System.identityHashCode(a4));
        System.out.println(System.identityHashCode(b4));
        System.out.println("4:"+(a4 == b4));
        System.out.println("------------------");
        Integer a5 = 128;
        Integer b5 = 128;
        System.out.println(System.identityHashCode(a5));
        System.out.println(System.identityHashCode(b5));
        System.out.println("5:"+(a5 == b5));

    }

输出:
工作中Integer类型传参遇到的陷阱
从上边的例子我们可以学习到:

  1. Integer i = new Integer(num);其实是创建了两次对象,一个对象的地址放堆中,一个放常量池中,例如:上边3的输出
  2. 如果i的返回在-127~128内,这个对象可以放到常量池中,所以如果定义的Integer i = 这个范围内,直接引用其地址,其实始就是同一个;但如果超出这个返回,将在常量池中重新创建新的对象,例如:上边4,5的输出
  3. Integer a2 = 60做的其实是Integer a2 = Integer.valueOf(60),自动装箱操作,在-127~128内,如果常量池中有这个对象,它们引用的就是常量池的对象。

通过上述的例子,可以解释遇到的问题

integer指向的是堆中的对象,i在常量池中也有相对应的对象,所以但我们将integer传入函数,并改变它的时候,修改的其实是它在常量池的地址对应的值,所以并不会引起integer真正的改变,因此它还是0!!

解决方案

如果一定要通过函数去修改这个integer的值,有如下方案:

  1. 改变的这个值integer用函数的返回值接收integer = fun();得到就是修改后的值,这个方法的看具体的业务场景。

  2. 自己封装一个 类class MutableInteger{ int value;}这个方法处理麻烦点

  3. 使用AtomicInteger原子整形对象

    AtomicInteger integer=new AtomicInteger(i);
    tempList = this.commonCalMainProcess(list,indexList,integer,position,null);
    int i = integer.intValue();
    
    void commonCalMainProcess(...,AtomicInteger ai...,){
    		ai.set(value);
    }