慎先森小站

4 object(s)
 

Java方法中修改参数,为什么有的成功有的失败?

运行以下代码打印输出结果会是什么?

    public static void main(String[] args) {
        int a = 10;
        int[] b = {1,2,3};
        String c = "中";
        setA(a);
        setB(b);
        setC(c);
        System.out.println(a);
        System.out.println(b[1]);
        System.out.println(c);
    }
    public static void setA(int a) {
        a=100;
    }
    public static void setB(int[] b) {
        b[1]=200;
    }
    public static void setC(String c) {
        c="国";
    }

答案是:10 200 中 。为什么修改变量a和变量c的值又变回去?

堆栈.png

setA方法在执行之前,main方法将a=10压入栈。当setA方法运行时将a=100压入栈。而当setA方法执行完毕,a=100被弹栈。其实就是setA压入栈的a超出作用域,所以打印输出a=10。

seB方法执行前b已经静态初始化,b变量在栈内存中,b的数组对象在堆内存中。setB方法得到的是b对象的地址值。b[1]=200也是直接修改了堆内存的对象值。所以setB方法结束后b[1]也是被修改了。

String是引用类型,按照上面理论应该也会被修改,但是并没有被修改。

其实String在作为实参传值给setC时,并不是传的String的地址值,而是String内容。

    //可以运行以下代码可知,String是传值,而非传址。
    public static void main(String[] args) {
        String c = "中";
        System.out.println(c.getBytes());
    }
    public static void setC(String c) {
        System.out.println(c.getBytes());
    }

既然传的不是地址值,在setC方法自然无法修改(字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享)。