- 先来说说String
而且是final修饰,这个才是String不可变的关键点
例如:String a=”a”; String b=”b” ;当执行String c=a+b操作时,实际上是创建一个StringBuilder对象,再通过apend()进行拼接,最后调用toStirng()生成一个新的对象给c。
注:因为有“final”修饰符,所以可以知道string对象是不可变的。
2、StringBuffer与StringBuilder
StringBuffer和StringBuilder的这部分源码基本一样,构造函数初始化大小都为16,都是继承了AbstractStringBuilder,AbstractStringBuilder中定义的变量value,是个字节数组,所以StringBuffer和StringBuilde的内容可以变。
1)
String和StringBuffer、StringBuilder相比,String是不可变的,String的每次修改操作都是在内存中重新new一个对象出来,而StringBuffer、StringBuilder则不用,并且提供了一定的缓存功能,默认16个字节数组的大小,超过默认的数组长度时,则扩容为原来字节数组的长度*2+2。
2).
StringBuffer和StringBuilder相比,StringBuffer是synchronized的,是线程安全的,而StringBuilder是非线程安全的,单线程情况下性能更好一点;使用StringBuffer和StringBuilder时,可以适当考虑下初始化大小,较少扩容的次数,提高代码的高效性。
3)
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
4)StringBuilder效率高于StringBuffer
字符串连接操作:
StringBuffer更高效,在连接时在原来对象上通过append方法添加,
String是在更改时,在内存中重新创建对象然后将原来的copy来,再做修改
Stringbuffer固然是线程安全的,stringbuffer固然是比stringbuilder更慢
5)
String的“+”:编译器建立StringBuilder、StringBuffer对象的append方法构造
例1:
public class Test {
public static void main(String[] args) {
String s1="hello";
String s2="world";
System.out.println(s1+":"+s2);//hello:world
change(s1,s2);
System.out.println(s1+":"+s2);//hello:world
StringBuffer sb1=new StringBuffer("hello");
StringBuffer sb2=new StringBuffer("world");
System.out.println(sb1+":"+sb2);//hello:world
change(sb1,sb2);
System.out.println(sb1+":"+sb2);//hello:worldworld
}
public static void change(StringBuffer s1,StringBuffer s2){
s1=s2;
s2.append(s1);
}
public static void change(String s1,String s2){
//String类型修改都是创建新的对象,而stringBuffer则可修改
s1=s2;
s2=s1+s2;
System.out.println(s1+s2);//worldworldworld
}
}
例2:
public class Test {
public static void main(String[] args) throws InterruptedException {
String a="link";
String b="link";
System.out.println(a==b);//true
System.out.println(a.equals(b));//true
//用""创建的a,b两个字符串,==和equals比较返回都为true,这是因为a,b都指向了方法区的同一个字符串。
//所以,当同样的一个字符串用""重复创建时只在方法区创建一次。
String x=new String("min");
String y=new String("min");
System.out.println(x==y);//false
System.out.println(x.equals(y));//true
//用new创建的c,d两个字符串,equals为true很简单因为equals永远比较的是值,而==为false说明两个字符串的引用不一样。
//用new创建的字符串每次都会在JVM堆中创建,所以c,d都对应堆中的两个不同的字符串
}
}
补充:
Integer c=new Integer(1);
//true:c!=a c==b c.equals(b) c.equals(a)
Integer a=1;
//true:a==b a.equals(b)
int b=1;