新建了一个线程类,构造参数为一个String,在run方法内将这个通过构造参数传入的String改个值,这个线程类就算完事了。
随后在另一个客户端类(main方法)中定义一个String并赋初始值。随后new一个先前创建的线程类,并将这个String作为构造参数传入。随后打印这个String。按照预期,打印出的应该是在线程类中run方法改过值后的结果,但结果却是这个Sting的初始值。即这个Sring被一个线程改过值后,回到主线程中并没有改变值。请高人赐教原因!!!代码大致如下:
public static void main(String[] args){
     String name = "original";
     Thread t = new Thread4(name);
     t.start();
     t.join();
     System.out.println(name);
}public class Thread4 extends Thread { @Override
public void run() {
name = "changed";
System.out.println("changing name to :" + name);
} String name;

public Thread4(String name){
this.name = name;
}
}
令我诧异的是,修改这个线程类的构造参数,传入一个自定义的对象,随后再run方法中更改传入对象的一个域,也是Stirng类型的。随后和上面的代码类似,在主线程中打印这个对象的域值,结果是改变后的值。问题是为什么Sting在一个线程中被更改后在主线程中看不见被更改后的结果,而自定义对象的String的域却可以??

解决方案 »

  1.   

    LZ能理解下面这段代码的问题,就清楚自己的问题了
    public static void main(String[] args) {
        String s = "old";
        change(s);
        System.out.println(s);
    }public static void change(String s) {
        s = "new";
    }
      

  2.   

    举个更简单一点的例子吧String s1 = "old";
    String s2 = s1; //这里就当作是s1传到方法,使得方法的参数s2=s1,
                      //其实就是让方法的参数指向了和方法外的s1一样的内存地址
    s2 = "new"; //这里就当作是方法的参数s2改变了,
                  //要注意,这里是改变了s2,让它指向新的内存地址,但是s1本身没有任何改变
    System.out.println(s1); //所以方法外的s1并没有变
      

  3.   

    首先感谢赐教,开发java有一段时日了,但是这个看似简单的问题却把我搞的有点糊涂了。首先我认为String在java中是引用类型。在调用了change方法后,将传入的name指向了"new",那在main方法中该是打印出"new",真不明白为什么还是"old"?
      

  4.   

    我在2L的解释很清楚了
    public static void main(String[] args) {
        String s = "old"; //这里的s相当于2L的代码的s1
        change(s);
        System.out.println(s);
    }public static void change(String s) {
        s = "new"; //注意这里的s相当于2L的代码的s2
    }首先要知道,每个方法都有自己的栈,方法内部的变量是在自己的方法栈里面的,也就是说change方法的s和main方法的s不是同一个,是各自方法栈里的变量,它们只是值相同,即它们都指向同一个字符串对象(也就是说它们引用的是同一个字符串对象),所以改变change方法的s,让它指向新的字符串对象(即让change的s引用新的字符串对象),并不会影响main方法的s(即main的s引用并没有发生任何改变),因为它们是互不相干的
    再来看一段代码
    public static void main(String[] args) {
        StringBuilder s = new StringBuilder("old");
        change(s);
        System.out.println(s);
    }public static void change(StringBuilder s) {
        s.append("new"); //注意这个例子和上面的例子的区别,这里发生的不是s=这样的处理
                          //也就是说没有发生s指向的改变,即change里的s和main里的s还是引用同一个对象
        s.append("I am the same value of s of main."); //所以这里发生的改变会影响main的s
                                //因为append是操作change的s所引用的对象的方法,
                                    //而main的s也在引用这个对象,所以方法发生的效果会影响到main的s    s = new StringBuilder("change"); //注意这里,发生了s=这样的处理,也就是说改变了s的指向,
                                            //即change里的s和main里的s不再指向同一个对象
                                            //change的s引用了新的对象,而main的s还是引用原来的对象
        s.append("I am not the same s of main"); //所以这里再发生变化,也不会影响main的s
    }