1、String 字符串常量,但是它具有不可变性,就是一旦创建,对它进行的任何修改操作都会创建一个新的字符串对象。
2、StringBuffer 字符串可变量,是线程安全的,和StringBuilder类提供的方法完全相同。如果查看java的源代码,就会发现它和StringBuilder类的方法的区别就是,在每个方法前面添加了"synchronized",保证其是线程安全的。
3、StringBuilder 字符串可变量,是线程不安全的。从jdk5中加入。
4、StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。
5、串池
//StringTest1
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2); // true
//StringTest2
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2); // false
java的String是不可改变的字符串对象。为了提高效率,java为String类提供了串池。在StringTest1中就使用了串池。当你重新声明一个String型变量为abc时,将使用串池里原来的那个abc,而不重新分配内存,也就是说,str2与str1将会指向同一块内存。所以结果为true。在StringTest2中使用了普通对象的声明方式,系统将会为str1和str2各分配一块内存。所以结果为false。
6、其他
String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s4 = "ab";
System.out.println("s3==s4 -> "+ (s3==s4)); //根据String的概念他们都指向了同一个缓冲池内的地址,所以结果为true。
String s5 = "a"+"b";
System.out.println("s3==s5 -> "+ (s3==s5)); //因为相加的两个为常量,所以编译器会把s5="a"+"b"优化为s5="ab",所以结果也为true。
String s6 = s1+s2;
System.out.println("s3==s6 -> "+ (s3==s6)); //因为是两个变量的相加所以编译器无法优化,s1+s2即等同于(new StringBuilder(String.valueOf(s1))).append(s2).toString(); 在运行时,会有新的String地址空间的分配,而不是指向缓冲池中的“ab”。所以结果false。
String s7 = new String("ab");
System.out.println("s3==s7 -> "+ (s3==s7)); //根据缓冲池的定义在new的时候实际会新分配地址空间,s7指向的是新分配的地址空间所以与缓冲池地址不同,所以为false。
final String s8 = "a" ;
final String s9 = "b" ;
String s10 = s8 + s9;
System.out.println("s3==s10 -> "+ (s3==s10)); //类似于s3与s5,因为是final类型编译器进行了优化所以相同。