String作为函数参数传递时,传值还是传址的疑惑

public class Test {

 /**
  * @param args
  */
 public static void change(String str){
  System.out.println("before = str*****" + str.hashCode());
  str = "welcome";
  System.out.println("after = str*****" + str.hashCode());
 }
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  //MyTestStr.demoStr();
  String str = "hello";
  System.out.println("str---" + str);
  System.out.println("str---" + str.hashCode());
  change(str);
  System.out.println("str---" + str);
  System.out.println("str---" + str.hashCode());
 
 }

输出结果为

before change,str-----hello
before change,hashcode of str-----99162322
before =,str*****hello
before =, hashcode of str*****99162322
after =,str*****welcome
after =, hashcode of str*****1233099618
after change,str-----hello
after change,hashcode of str-----99162322

 

如果你在没有执行=之前输出hashcode,那么这个编码应该是和main方法里面的a的hashcode相同的。
但是当你执行了=之后,这个hashcode应该已经不同了,它们不是同一个对象

看一下String类的源代码,因为String用了一个private final char value[]来保存字符串,也就是这个字符串一旦创建,就不可以修改,直接导致了String类没有set方法。我们也就没法修改String中内容,当你用=给String赋值时,实际上并没有修改原先那个引用的值,而是新给了一个值

 一个变量被当作参数传入了方法,Java是把这个变量的值传入这个方法里面——String是一个应用类型,它在堆里面的值就是一个引用,因此传String的变量到方法,事实上传的是这个引用。当你对这个变量进行赋值的时候,修改的是这个变量的值,而不是这个变量指向(引用)的对象,即可以更改变量引用的地址,但不能改变引用的内容
    如果你要一个String传入一个方法后,方法里面对该String的修改对方法外面有效的话,你可以用StringBuffer,并且在方法里面不是直接对这个变量进行赋值,而是通过StringBuffer的方法对这个字符串的对象进行操作,如append,不过这严格来说也不是String对象了。
   

再如String a1 = "a1";a1=a1+"bb"时,相当与String tmp=new  String(a1) + new String("bb");  a1=tmp;
这样容易看出tmp指向重新在堆中分配内存,a1作为引用被重新赋值不再指向a所指向的堆内存,说明此时a1和a没有任何关系,不难理解了!

 

你可能感兴趣的:(String)