【Java基础】基本类型的包装类做为参数传递是值传递仍是引用传递

忽然想到这个问题,而后作了下实验,下面以Integer来说解,其余的忽略:java

import java.util.Iterator;

/**
 * Created by lili on 15/9/24.
 */
public class TestNew {
    public static void main(String args[]){

        Integer i1 = 10;
        Integer i2 = 20;
        System.out.println(i1   + "   " + i2);
        change(i1,i2);
        System.out.println(i1   + "   " + i2);

        String s1 = new String("s1");
        String s2 = new String("s2");
        System.out.println(s1 + "   " + s2);
        change(s1, s2);
        System.out.println(s1   + "   " + s2);

        StringBuilder sb1 = new StringBuilder("sb1");
        StringBuilder sb2 = new StringBuilder("sb2");
        System.out.println(sb1   + "   " + sb2);
        change(sb1,sb2);
        System.out.println(sb1   + "   " + sb2);

    }

    public static void change(Integer i1, Integer i2){
        i1 = 100;
        i2 = 200;
    }

    public static void change(String i1, String i2){
        i1 = "ii1";
        i2 = "i22";
    }

    public static void change(StringBuilder i1, StringBuilder i2){
        i1.append("sbsbsb1");
        i2.append("sbsbsb2");
    }
}

运行结果:app

10   20
10   20
s1   s2
s1   s2
sb1   sb2
sb1sbsbsb1   sb2sbsbsb2

Process finished with exit code 0

 

事实证实,只有StringBuilder是引用传递,其余的仍是值传递。优化

按照常理,应该传递的是对象的地址,难道这里是由于作了自动装箱和拆箱,编译器帮你作了这个致使最后是值传递了?ui

带着这个问题首先去看了class文件的反编译代码:spa

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class TestNew {
    public TestNew() {
    }

    public static void main(String[] var0) {
        Integer var1 = Integer.valueOf(10);
        Integer var2 = Integer.valueOf(20);
        System.out.println(var1 + "   " + var2);
        change(var1, var2);
        System.out.println(var1 + "   " + var2);
        String var3 = new String("s1");
        String var4 = new String("s2");
        System.out.println(var3 + "   " + var4);
        change(var3, var4);
        System.out.println(var3 + "   " + var4);
        StringBuilder var5 = new StringBuilder("sb1");
        StringBuilder var6 = new StringBuilder("sb2");
        System.out.println(var5 + "   " + var6);
        change(var5, var6);
        System.out.println(var5 + "   " + var6);
    }

    public static void change(Integer var0, Integer var1) {
        var0 = Integer.valueOf(100);
        var1 = Integer.valueOf(200);
    }

    public static void change(String var0, String var1) {
        var0 = "ii1";
        var1 = "i22";
    }

    public static void change(StringBuilder var0, StringBuilder var1) {
        var0.append("sbsbsb1");
        var1.append("sbsbsb2");
    }
}

源代码显示并无作值传递的优化,由于若是作了,应该change中的参数会改成int,这样一来Integer对象会自动拆装为int进行值传递,一种自动装卸拆箱的代码示例以下:debug

 Integer integer = 11;
 integer += 9;

 /*
 Integer integer = Integer.valueOf(11);//自动装箱
 integer = Integer.valueOf((integer.intValue() + 9));//自动拆箱再装箱
  */

那到底是什么缘由呢?3d

带着这个问题,对程序进行了debug,看看传递的是不是对象地址。code

进入change方法后,看地址的变化对象

发现传入的是地址值,change参数的i1和i2的对象指向Integer@417和Integer@418,说明指向和传入参数的同一个对象,传入的是地址。blog

接着执行方法change程序:

执行改变i1的值时,此时i1指向的对象改成了Integer@427,至此能够充分说明不是自动装箱和拆箱的问题了,可是究其缘由,个人理解仍是和这个相关,由于执行到这一步的时候是i1 = 100;可是具体编译器优化后作了自动装箱处理,var0 = Integer.valueOf(100);因此i1指向了Integer.valueOf(100)这个新产生的对象,因此最后和值传递的效果同样,不会改变调用该方法的参数的值。

相关文章
相关标签/搜索