java是传值的应该如此理解:当数据是基本数据类型时,传值;当数据为对象时,传递对象的句柄(对象的地址值)。所以传递数组时实际传递的是数组对象的句柄,而不是将数组内容复制一份传入,这一点和C语言是不同的

解决方案 »

  1.   

    这个我知道,但是现在的问题是,为什么会出现这样的情况:
    当对数组中一个元素更改后(就像例子中那样),就能够改变该元素的值---“Java是传值的”在这里好像发生了错误(这正是讨论的重点)。
      

  2.   

    还有  public static void main(String args[]){
        String s[] = new String[3];
        s[0] = "0";
        s[1] = "1";
        s[2] = "2";
        String ss[] = new String[3];
        ss[2] = s[2];
        ss[2] = "3";
        System.out.println(ss[2]+"  "+s[2]); 
      }
    结果就是:3  2
    但是,下面的结果就大不一样:
      public static void main(String args[]){
        String s[] = new String[3];
        s[0] = "0";
        s[1] = "1";
        s[2] = "2";
        String ss[] = new String[3];
        ss=s;
        ss[2] = "5";
        System.out.println(ss[2]+"  "+s[2]);
      }
    结果就成了 : 5  5
      

  3.   

    没错
    数组传递的也是引用
    所以s[] sb[]是同一个数组的引用
    其成员内容当然相等 为6
      

  4.   

    Java 中,基本数据传值 , Object 对象就是传引用.数组 是一种特殊的 Object 对象(因为要用 new 生成的都是 Object) .所以传递的也是引用.至于 String 是不可变类,也就是其内容是不变的, 我们更改一个 String 的值,其实是生成了另一个 String 对象.
      

  5.   

    我认为javacomte(基督山伯爵)的"传递数组时实际传递的是数组对象的句柄"已经说得很清楚了,就上面的程序来说,当你执行 ss = s;这个语句时,就让ss指向了s 的地址,也就是说ss与s是同一个地址,
    所以他们中不论是改变谁的值,另一个也会改变。
      

  6.   

    说的再详细点:
    public static void main(String args[]){
        String s[] = new String[3];
        s[0] = "0";
        s[1] = "1";
        s[2] = "2";
        String ss[] = new String[3];
        ss[2] = s[2];
        ss[2] = "3";
        System.out.println(ss[2]+"  "+s[2]); 
      }这个是3 2
    ss[2] = s[2]; 这个传递的是值

    public static void main(String args[]){
        String s[] = new String[3];
        s[0] = "0";
        s[1] = "1";
        s[2] = "2";
        String ss[] = new String[3];
        ss=s;
        ss[2] = "5";
        System.out.println(ss[2]+"  "+s[2]);
      }
    当中.
    ss = s 就跟上面不一样了.ss,s都是reference,也就是句柄,他们是保存在栈当中的.他们指向堆中的string array object
    你让ss =s .就是让这两个reference都指向了同一个对象(object),你改变了ss,s也跟着变了.其实是因为它们操控的是同一个东西.在上面的例子中.你让ss=s.此刻ss指向的就是String s[] = new String[3]; 产生的对象.所以你改变了ss,s的值也就发生了变化.你可以看看Thinking in java 的附录A.
      

  7.   

    让我们从新来过。
    其实binny(骑个破车看夕阳)  abcdhy(程旭) zhaobao() 说的都很有道理
    在java中,array其实也是一个object
    让我们来看看你的第一个例子。在这个例子当中。你使用了  
    t.setArray(t.s[3]);
    public void setArray(StringBuffer sb) { //
        //s=null;
        sb = new StringBuffer("6"); //
      }看这个t.setArray(t.s[3]);不好意思。我要去上课了。呵呵。SORRY。
    晚上回家继续
      

  8.   

    我将程序改了一下,输出整个String数组
    class Test2
    {
    public static void main(String[] args)
    {
    String s[] = new String[3];
    s[0] = "0";
    s[1] = "1";
    s[2] = "2";
    String ss[] = new String[3];
    ss[2] = s[2];
    ss[2] = "3";
    for(int i=0;i<s.length;i++)
    System.out.println(ss[i]+" "+s[i]);
    }
    }
    程序结果如下:
    null 0
    null 1
    3 2
    也就是说s[]只是将s[2]的值赋给了ss[2],他们指向的内存地址不同,也就是两个地址空间,所以改变ss[2]只是在它的地址里写入3,s[2]没改变
    class Test3
    {
    public static void main(String args[])
    {
    String s[] = new String[3];
    s[0] = "0";
    s[1] = "1";
    s[2] = "2";
    String ss[] = new String[3];
    ss=s;
    ss[2] = "5";
    for(int i=0;i<s.length;i++)
    System.out.println(ss[i]+" "+s[i]);
    }
    }
    程序结果如下:
    0 0
    1 1
    5 5
    在ss=s中,是将s[]数组的首地址赋给ss[],也就是指向同一个对象,本质上在内存中只有一个存储空间,所以对他们的操作都会改变这个地址所存储的值
      

  9.   

    楼猪,我将你的程序改了一下,如下:
    class Test
    {
    public Test()
    {
    } public StringBuffer s[];
    public static void main(String args[])
    {

    Test t = new Test();
    t.s = new StringBuffer[4];
    t.s[0] = new StringBuffer("1");
    t.s[1] = new StringBuffer("2");
    t.s[2] = new StringBuffer("3");
    t.s[3] = new StringBuffer("4");

    t.setArray();
    for (int i = 0; i < t.s.length; i++)
    {
    System.out.println(t.s[i]);
    }


    t.setArray(t.s[3]);
    System.out.println("#######################################################");
    System.out.println(t.s[3]);
    for (int i = 0; i < t.s.length; i++)
    {
    System.out.println(t.s[i]);
    }

    }

    public void setArray()
    {
    s[3] = new StringBuffer("5");
    }

    public void setArray(StringBuffer sb)
    {
    //s=null;
    sb = new StringBuffer("6");
    System.out.println("sb="+sb);
    /*if(this.sb==sb)
    System.out.println("this.sb have the same value of sb");
    if(this.sb.equals(sb))
    System.out.println("this.sb have the same addr with sb");
    */
    }
    }输出如下:
    1
    2
    3
    5
    sb=6
    #######################################################
    5
    1
    2
    3
    5
    sb是一个值(我改动了你的setArray()方法)class Test1
    {
    public Test1()
    {
    }

    public StringBuffer s[];
    public static void main(String args[])
    {
    Test1 t = new Test1();
    t.s = new StringBuffer[4];
    t.s[0] = new StringBuffer("1");
    t.s[1] = new StringBuffer("2");
    t.s[2] = new StringBuffer("3");
    t.s[3] = new StringBuffer("4");

    t.setArray();
    for (int i = 0; i < t.s.length; i++)
    {
    System.out.println(t.s[i]);
    }

    t.setArray(t.s);
    System.out.println("#######################################################");
    System.out.println(t.s[3]);
    for (int i = 0; i < t.s.length; i++)
    {
    System.out.println(t.s[i]);
    }

    }

    public void setArray()
    {
    s[3] = new StringBuffer("5");
    }

    public void setArray(StringBuffer sb[])
    {
    //s=null;
    sb[3] = new StringBuffer("6");
    System.out.println("sb="+sb);
    }
    }
    输出如下:
    1
    2
    3
    5
    sb=[Ljava.lang.StringBuffer;@45a877
    #######################################################
    6
    1
    2
    3
    6sb是一个地址,对数组的地址的操作才能改变数组所指向的值
      

  10.   

    OK.酒足饭饱.:P
    让我们从新来过。其实binny(骑个破车看夕阳)  abcdhy(程旭) zhaobao() 说的都很有道理
    在java中,array其实也是一个object这个问题其实并不复杂.只是楼主的例子写的复杂了.和和:)让我们来看看你的第一个例子。在这个例子当中。
    1.Test t = new Test();
    我们来分析一下
    此刻.我就用[]来表示一个new生成的对象吧,--->表示从reference指向objectt ---------------------> test[]2.然后, t.s = new StringBuffer[4];
    其实就是让s指向一个array objects ---------------------> an stringbuffer array object[]3.下面,你给这个数组里的元素赋值
        t.s[0] = new StringBuffer("1");
        t.s[1] = new StringBuffer("2");
        t.s[2] = new StringBuffer("3");
        t.s[3] = new StringBuffer("4");
    其实你这里的s[0],s[1],s[2],s[3]就是一个个的reference,对吧?
    你给他们赋值.其实就是让它们分别指向一个个的stringbuffer object.s[i] --------------------------> an stringbuffer object[]4.t.setArray();你调用了setArray()方法
      public void setArray() {
        s[3] = new StringBuffer("5");
      }
    你让原来的s[3]放弃了原来的stringbuffer object对象.转而指向一个新的对象.也就是说此刻s[3]=5
    s[1] --------------------------> an stringbuffer object[2]
    s[2] --------------------------> an stringbuffer object[3]
    s[3] ----------------    ×      an stringbuffer object[4]  //他被抛弃.待会GC会回收他
                         |
                         |---------> an stringbuffer object[5]  //s[3]转而指向这个对象5.最关键的到了.你让t.setArray(t.s[3]);
    你此刻传递的是s[3]这个reference的拷贝引用,
    sb = new StringBuffer("6");s[3] --------------------------> an stringbuffer object[5]
      |
      |
     sb(SB??what's mean?? :P) ---------> an stringbuffer object[6]然后你打印数组.s[3]还是s[3],当然还是5啦~如果你将setArray(StringBuffer sb)改成这样
      public void setArray(StringBuffer sb) {
        //s=null;
        sb = new StringBuffer("6");
        s[3] = sb; // ! 变啦~
      }
    看看结果是什么? :)   == 1,2,3,6
      

  11.   

    告一段落.我们来看第二个:
    ___________________________________________________________1.上面的都一样.我们来看最关键的
    你让 t.setArray(t.s);    //!!!!请看这里传递的是什么?
    MY GOD~~传递的是这个! s这个array reference的拷贝引用
    s ---------------------> an stringbuffer array object[]注意看这个
      public void setArray(StringBuffer sb[]) {
        //s=null;
        sb[3] = new StringBuffer("6");
      }就是这个sb[3] = new StringBuffer("6");你让他直接改变了s[3]的值
       s     --------------------> an stringbuffer array object[]
       |                               s[i] --------------> an stringbuffer object[i]
       |          |------------->      s[3]  ------  ×     an stringbuffer object[5]
      sb[3]  -----                                    |
                                                      |--->  an stringbuffer object[6]当然上面的图可能不太符合规则.供楼主加深一下了解吧.关于pass by value还是pass by reference.java社区争论已久,不过我觉得我们没有必要在这个上面浪费时间
    其实javacomte(基督山伯爵) abcdhy(程旭) 说的非常清楚.我是个笨人.无法用精练的语言来表达.只有用图像来表示.
    和和~~:)
    建议楼主.
    1.多看看thinking in java,经典还是经典
    2.不用在这些方面花太多的功夫.有了概念就好.我想在工作中.写出这样绕人的程序机会还是很少的.和和~~
    简洁就是美~