public class Example {
String str=new String("good");
char[] ch={'a','b','c','d'};
int i=10;
public static void main(String[] args) {
Example ex=new Example();
ex.change(ex.str, ex.ch,ex.i);
System.out.println(ex.str);
System.out.println(ex.ch[0]);
System.out.println(ex.i);
}

public void change(String str,char[] ch,int n){
str="test ok";
ch[0]='g';
n=9;
}
}
//正确答案是:
//good
//g
//10
那位仁兄能详细地给我分析一下这个题目,怎样理解传值与传地址呢?越详细越好!高分相送,非常感谢!
凑热闹的请走开!

解决方案 »

  1.   

    我估计你的疑问就是在ch这个数组这里,为什么ch[0]输出的g,对吧数组变量存放在内存的栈(heap)中,而数组元素则存放在内存的堆(stack)中。
    计算机访问数组,实际是通过对数组引用变量的引用,利用数组引用变量所指向的堆内存空间,来访问数组的元素。
    而你程序中ch[0]='g';这句话 实际上就是改变了堆内存空间的值
    str="test ok";与n=9;这两句话只是新开辟了栈空间存放临时变量
      

  2.   

    str="test ok";n=9;可以理解为给局部变量str和n赋值,对外面的str和i没影响ch[0]='g';给数组ch所指向堆内存中的第一个元素赋值
    ch指向的内存地址没变,里面的内容变了
      

  3.   

    #2楼正解
    ex.str,ex.i都是指向栈内存(值)空间的,而ex.ch则是指向堆内存(地址)空间的,所以ex.str、ex.i传的是值,ex.ch传的是地址,任何时候对数组的操作都是对其指向的地址所指向的值的修改。
      

  4.   

    二楼的理解正是我的疑问之处!另外还有一个疑问,String str=new String("good");这里str是对象类型,经过change方法调用,它的引用(或者说地址)发生了变化,为什么str的值还是good,而不是test ok呢?
      

  5.   

    public void change(String str,char[] ch,int n){
            str="test ok";//这里的str只是一个形式变量,是str参数的一个副本,所以改变它,不会影响
    //原来的参数str,并且在change方法结束之后,该副本就不再被引用;下面的n一样的道理
            ch[0]='g';//数组变量存在stack中,而值也就是各元素存在于heap中,变量指向具体的值,所以
    //你这句代码指向了heap中的另一个地址,改变了ch数组原来的值了。
            n=9;
        }
      

  6.   

    整体来说:如果是对引用进行操作,那么不会改变该引用所指向的对象的值
    如果说是对对象进行操作,那么就改变了对象的值了
    1;对String引用操作,所以不改变其对象的值
    2:对数组对象的操作,这里你可能迷糊了,其实ch[0]不是引用,在JVM里,是一条指令根据这个数组引用和索引找到给定数组的指定索引位置的值压入栈,ch[0]相当于ch.get(0),所以是对于ch所指向的对象直接操作,即改变了对象的值
    3:n是基本类型,是在change()里的一个临时变量,所以不影响外部的n
      

  7.   

     public void change(String str,char[] ch,int n){
            str="test ok";
            ch[0]='g';
            n=9;
        }
    这里面的String str,char[] ch,int n调用的是参数,函数里面的  str="test ok";
            ch[0]='g';
            n=9; 也分别是参数 因此不会对类中的变量进行改变,建议楼主测试一个简单的例子public class Example {
        int i=10;
        public static void main(String[] args) {
            Example ex=new Example();
            ex.change(ex.i);
            System.out.println(ex.i);
        }
        
        public void change(int n){
       n=9;
        }
    }输出为10 如果你在函数中change 添加 public void change(int n){
       n=9;
     System.out.println(n);    }
      

  8.   

    基本数据类型byte,short,int,long,float,double,char,boolean都是值传递,其他都是引用类型,是地址传递。
    在调用change方法时,会临时分配三个临时变量:str,ch,n。
    n是值传递,n的值变为9,但是i不变。ch是数组,是地址传递,所以方法change里面的ch和类ex的ch指向同一个数组:{'a','b','c','d'},故不难理解ex.ch[0]也随之变为g。
    那么楼主可能会对String有点疑问。String也是地址传递,字符串的值是放在常量池中的,比如str,当创建good时,发现常量池中没有就在常量池中创建good并把good的地址赋给str,但是请注意这句话:str="test ok";
    这句话并不是将str所指向的字符串值good改为test ok,其实是又新建了一个常量 test ok,然后将该字符串的地址赋给change方法中的临时变量str,但是类ex中的sr还是指向原字符串good。这点要非常注意。
      

  9.   

    所谓的地址传递传递的是变量的地址,如果我们把地址看做一个值的话,那么它也是一种“值传递”。
    change方法里的语句:str="test ok"; 并不是将str所指向的字符串值good改为test ok,其实是又新建了一个常量 test ok,然后将该字符串的地址赋给change方法中的临时变量str,而类ex里的str的值(也就是地址)并没有变,仍然指向原来的字符串值good。
      

  10.   

    在java里面只有值传递,但是值传递的实质就是传递变量的地址,不管是基本类型还是引用类型都是这样。同一个地址对于基本类型来说值肯定是相同的;不好理解的是引用类型的变量。我打个比方:把地址分为栈地址和堆地址的话,引用类型的变量存放的是该对象在堆中所在的位置,对象一般是由成员变量,方法构成,如果成员变量也是引用类型的话,该变量又会指向堆中的某个地址,你改变栈中的地址,对象就改变了;但是如果你只是改变堆中变量的地址,对象没变,只是它的成员变量发生了改变。简单一句话:对于引用类型来说改变一级地址的值,整个对象都变了;改变二级或更下级地址的值,对象没变,只是对象所拥有的变量发生了变化。要特别注意的是对于一些不可改变的量,在java中都是有对应的池的,如String类型的变量,虽然你将该变量作为实参传给了形参,并不会影响该变量的值;除非你将返回的字符串赋值给这个变量,那样才会改变。
      

  11.   

    LZ还是看看4楼的解释吧,没必要绕得那么复杂。把你的change方法里的str改成this.str,你要的test ok就可以 出来了。至于数组对象,上面解释很清楚了;n只是一个局部变量(就你的程序来看),怎么会对ex的i属性有影响呢。
      

  12.   

    要点1:java中只有值传递。引用传递传递的只是堆中的地址。要点2:String对象是终态对象,每次改变都会重新return 一个新的String对像
           String s = "s";
          String s += "d";  //此时的s对象已经和上面的不是一个对象了,在堆中的地址已经改变。
           
           java源码中  不管对String如何操作最后都会返回一个新的String类型要点3:数组为引用类型
      

  13.   

    Java里面个人认为只有引用和数值传递,其实引用也是地址,只不过是对象在创建的时候在堆中分配了一块内存,然后将内存地址交给存储在栈里面的声明的那个对象变量,然后我们用的时候以为用的是对象,其实用的是对象的地址,但是在java里面这叫做引用。
    而数值就是基本的数据类型才有的传递方式。
      

  14.   

     str="test ok"; 你改变的数组内的值
     ch[0]='g';你把第一个变成了G
     n=9;你把值给换个
    对不起 没有RETURN你做的全部白做,应为是值传递就像C里面的你换完数不返回不白做么
      

  15.   

    我告诉你为什么 ,因为String是一个很特殊的不可变类,建议你回去满String的api或者网上搜索一下String.究竟有什么特殊呢,String一旦创建了,他的值在内存中是不变的,System.out.println(ex.str);
    你这句话只是输出了引用名为str的String,他在内存中的内容不能变,而且你也没有把str指向其他内存块,所以这个str还是老老实实地指向"good",你方法里面
    public void change(String str,char[] ch,int n){
            str="test ok";
            ch[0]='g';
            n=9;
        }的str是代表另外一个引用,所以你只是把方法里面的引用给了指向"test ok";所以说你原来的main方法那个str还是指向"good"
      

  16.   

    1. java只有值传递
    2. String虽然是一经创建初始化之后就不变,但是跟这里的没有关系,因为change方法里的str只是原始ex.str的一个副本,是个形式参数,在方法change执行完了之后,就会被销毁(不一定是马上)。
      

  17.   

        我是这样理解的:change方法中的参数str 同进也指向了{'a','b','c','d'}这个字符数组,此时就是说有两个引用都指向了这个字符数组,至于为什么变量名都一样,我个人认为形式参数中的String str 应该相当于变量声明。当在方法change中为参数str赋值后,相当在内存中开辟新的空间,然后赋值并把地址引用赋给参数str,而全局变量的str仍然引用{'a','b','c','d'}的内在地址,所以值没有变化。
        我这是用白话讲的,说的不对的地方请大家指教。