黑马程序员技术交流社区

标题: Java在方法中修改字符串和数组数值区别 [打印本页]

作者: 张鹏宇    时间: 2014-5-12 14:15
标题: Java在方法中修改字符串和数组数值区别
本帖最后由 张鹏宇 于 2014-5-12 21:21 编辑


public class Other {
        
                public static void main(String[] args) {
                                 int[] num = new int[]{1,2};
                                 int a = 1;
                                 String s = new String("abc");
                                 method(a,num,s);
                                 System.out.println(a);
                                 System.out.println(num[1]);
                                 System.out.println(s);
                }

                public static void method( int a,int[] x, String s){
                          a = 2;
                         x[1] = 50;
                         s = "abcd";
                }
               

}
数组的数值会被改变,字符串不会,请问一下整个过程堆栈操作原理。
作者: vampire.007    时间: 2014-5-13 16:36
这里简单的说就是值传递和引用传递的过程
作者: 张鹏宇    时间: 2014-5-16 17:47
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  

答案基本上是:值传递

说明:得出这种结论的前提必须是“参数的值就是对该对象的引用,而不是对象的内容”

----------------------------------------------------

值传递:方法调用时,实际参数把它的值传递给对应的形式参数,方法中执行形式参数值的改变不影响实际参数的值。

引用传递:也称为传地址。方法调用时,实际参数的引用(即地址,而不是参数的值)被传递给方法中相对应的形式参数,

在方法中执行对形式参数的操作实际上就是对实际参数的操作(地址操作),这样方法执行中形式参数值的改变将会影响实际参数的值。



1.      基本类型传递

基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的, 值都存在栈中。

public class Other {

        public static void main(String[] args) {

                     int a = 1;

                     method(a);

                     System.out.println(a);

                  

        }



        public static void method( int a){

             a = 2;

        }

}

输出: a = 1;

2.      类传递

Case 1:

public class Other {

        public static void main(String[] args) {

            StringBuffer s = new StringBuffer("abc");

            method(s);

            System.out.println(s);         

        }

        public static void method(StringBuffer s){

             s = new StringBuffer("abc");

             s.append("d");

        }

}

输出:abc

解析:这时传递的是对象的地址,方法中的s又重新创建了对象“abc”,这时他们引用两个不同堆内存。s.append是在method创建出的“abc”上加“d”,所以会main中不会变。



Case 2:

public class Other {

        public static void main(String[] args) {

             StringBuffer a = new StringBuffer(“abc”);

             method(a);

             System.out.println(a);

        }

        public static void method( StringBuffer a){

             a.append(“d”);

        }

}

输出:abcd

解析:这时传递的是对象的地址,方法中的s同样指向 main中s的指向“abc”, s.append是将“abc”加上“d”,method直接修改这个值,所以会main中也跟着变。



Case 3:

public class Other {

        public static void main(String[] args) {

                    

                     String s = new String("abc");

                     method(s);

                     System.out.println(s);

                    

        }



        public static void method(String s){

             s = s+"d";

        }

}

输出:abc

在方法中改变String值





因为在a的值是个地址。所以传的值也就是0x0001,然后方法中的a也指向堆内存的“aaa”。当a=“bbb”时,方法区中的a 指向0x0002。所以main中的a 还是不变的。与case2不同的是String是不可变的,s+”d”是将存有abc的字符数组的值取出再加上d. 总之一定不是在原有的“aaa”上进行操作,这牵扯到String的安全性设计。

3.      数组传递

public class Other {



    public static void main(String[] args) {

        int[] a = new int[] { 1, 2 };

        method(a);

        System.out.println(a[0]);

    }



    public static void method(int[] a) {

        a[0] = 0;

    }

}

输出:2

数值为什么会改变呢





因为数组的地址和数组中值的地址中间又多了一道。传递到Method的b是main中b的值,也就是数组在堆中的地址0x0003,然后在这个数组中,第一个值又指向堆中的数值1,也就是0x0004 这时method 做b[0]=0,也就是把 数组中的第一位由0x0004改成0x0006,直接操作了该数组。
作者: 铁血丹心    时间: 2014-5-18 12:26
public static void method(String s){

             s = s+"d";
原理上应该是s = new StringBuffer().append(s).append("d").toString();,生成了一个新的字符串

作者: 黄梁梦想享    时间: 2014-6-5 10:39
:(:(看头晕了,回去好好学习去




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2