StringBuilder和StringBuffer的char[]可变的,String的char[]是不可变final的。StringBuilder效率高,但是线程不安全;StringBuffer线程安全,但是效率不高。为什么String设计为不可变的,因为线程安全和String实现值传递,而不是引用传递。
Java方法之间传递其实是引用副本的传递:代码如下:
public String change(String s, int i, StringBuffer sb, Person p){ s="123"; //改变传递引用副本 i=3; sb.append("woshi"); //改变传递值内容 p.setAge(100);//改变传递值内容 sb = new StringBuffer("sbsb"); //改变传递引用副本 p = new Person("bb",44); //改变传递引用副本 return s; } public void testChange(){ StringBuffer sb = new StringBuffer("buff"); String s = "aaa"; int i = 1; Person p = new Person("aa",12); i=2; change(s,i,sb,p); // s="222"; System.out.println(s); System.out.println(i); System.out.println(sb.toString()); System.out.println(p); } 输出: aaa 2 buffwoshi Person [name=aa, age=100]从虚拟机角度理解:
这个问题只要站在java虚拟机的角度上就能很好的理解了,很简单的,首先局部变量与方法参数都会存储在棧空间,new 出来的存储在堆空间,当程序执行stringbuffer sb=new stringbuffer(),首先会在棧空间分配一个变量sb(一个引用地址),然后会在堆空间分配一个实实在在的对象,sb指向这个对象,当调用change(stringbuffer sb)方法后,棧空间会copy一份sb的一个引用,也指向堆空间sb这个对象(此时棧空间有俩sb引用变量,并且同时指向同一个对象),执行sb.append(”aa”)后,会更改sb对象内容没问题,当执行sb=new stringbuffer();时copy的那个sb引用会重新指向一个新new出来的对象,方法执行完后棧空间copy的那个sb引用变量消失(如果没有其他引用指向它,它就会等待垃圾回收器的回收),回到主方法后,首次声明的sb引用依然指向原来的sb对象。
部分摘自:https://www.cnblogs.com/woshimrf/p/5263018.html