哪位大牛可以解释下此经典问题!程序运行的结果是什么?可否有详细解说

public class TestDemo {
String str=new String("good");
char[] ch={'a','b','c'};
public static void main(String args[]){
TestDemo ex=new TestDemo();
ex.change(ex.str,ex.ch);
System.out.print(ex.str+"and");
System.out.print(ex.ch);

}
private void change(String str, char[] ch) {
str="test ok";
ch[0]='g';

}
}

    首先你要明白,这是很明显考察Java是传值还是传引用的经典问题。
    在你提出的这个问题,首先一个如果是基本数据类型,毫无引用肯定是值传递的方式。
    问题就在如果是引用数据类型呢?是传值还是传引用,答案是传引用的值,从根本意义上来说还是传值不过是传引用的值。
    所以可以说Java既是传值又是传引用,也可以说Java就是传值,关键就看你自己怎么解释这个问题了。
    回到这道题,首先一个参数是String类型,引用类型的。但是String类型是一个很特殊的引用类型,即是final修饰的,不可变。
    当你调用change方法时,String类型的参数将指向“good”String的引用传递给str形参,在change方法中,对其进行修改赋值,
    对String类的任何改变,都是返回一个新的String类对象.这样的话把String类的引用传递给一个方法,该方法对String的任何改变,对原引用指向的对象没有任何影响,这一点和基本数据类型相似。
    而如果是数组引用类型就可以直接进行修改了。传的是引用,引用指向的值变了,因此也就变了。

    以上。

结果是ex.str还是good,而ch变成gbc
因为str改变的是引用,但是不会作用到实参,而ch改变的是数组本身。
如果是
private void change(TestDemo ex, char[] ch)
{
ex.str="test ok";
ch[0]='g';
}

...

ex.change(ex,ex.ch);
则可以改变str

首先发代码的时候注意一下格式!
答案是这个:goodandgbc
这是个非常简单的题,传入change的str是字符串,所以str的值是在常量池中存储,chang中str="test ok";只是将str的值(也就是常量池中的引用地址)发生改变,但"good"在常量池中没有发上改变所以这里只是值传递不会改变结果
ch传入的是一个数组,这里传入的是一个引用地址,将地址的值发生改变,回到main中的时候ch[0]地址所对应的值发生了改变,而地址不变,所以a就变成了g

goodandgbc

如果你熟悉C++的话,我可以告诉你Java的引用就是C++指针的拷贝,要深刻理解这句话。
str="test ok";这句代码中的str只是new String("good")的一个引用拷贝,使其引用到新的对象"test ok"不影响外部str的引用指向;
对于char[] ch,不同于C++,java中数组也是对象。此时内部ch仍然是一个外部ch的引用拷贝,两者ch[0]都是同一个位置。

了解其赋值过程即可,

搞清楚堆栈,哪个是放在堆的哪个是放在栈的。这样再来理解这个问题就简单了

    那么现在问题又来了,如果说change方法是下面这个样子的呢?
        private void change(String str, char[] ch) {
                str="test ok";
            ch = new char[]{'1','2','3'};
    }
    那请问字符数组输出答案变不变呢?

    答案是不变。这又是为什么呢?使用new就又重新开辟了堆栈空间,引用值就变了,这就像是str = “test ok ”返回的引用值也变了一样,
    变得是形参的str和ch而题目输出的是ex对象的属性值,这个值是没有变化的。

    以上。

package com.test.day0902;

public class ValueOrReference {
String str=new String("good");//new方式创建字符串对象会在堆栈开辟空间
char[] ch={'a','b','c'};
int a=4;
public static void main(String[] args) {
ValueOrReference ex = new ValueOrReference();
ex.change(ex.str,ex.ch,ex.a);
System.out.println(ex.str);//str没变
System.out.println(ex.ch);//ch[0]='g'变
System.out.println(ex.a);
}
private void change(String str, char[] ch,int a) {
str="test ok";
ch = new char[]{'1','2','3'};
a=9;
}
}