String, StringBuffer and StringBuilder考点:
-
可变性
String 不可变
StringBuffer 和 StringBuilder 可变 -
线程安全
String 不可变,因此是线程安全的
StringBuilder 不是线程安全的
StringBuffer 是线程安全的,内部使用 synchronized 进行同步
String类在Java的java.lang.String包下面,需要特殊说明的是String类是final关键字修饰,也就是不能被继承,String中的内容被创建后不能被修改。
String在Java内存存储:
在java中相关对象的引用变量一般都存在栈中,而相关的对象都是存在堆中的,栈中的值指向了它所引用的对象(堆中相应的对象的地址)。
栈:由JVM分配区域,用于保存线程执行的动作和数据引用。栈是一个运行的单位,Java中一个线程就会相应有一个线程栈与之对应。一般是用于存储的基本数据类型的局部变量(注意这里仅仅是局部的,对于全局变量不能这样定义)。
堆:由JVM分配的,用于存储对象等数据的区域。一般用于存储我们new出来的对象。
常量池:在堆中分配出来的一块存储区域,用于存储显式的String,float或者integer。例如String str=“abc”;abc这个字符串是显式声明,所以存储在常量池。
String str=new Stirng(“xyz”); //创建了几个对象
String str2=“abc”;//创建了几个对象
首先说“String str=new Stirng(“xyz”);创建了一个或者两个。对于“xyz”这个对象而言,它是存放在字符串的缓冲区中的,不管出现多少遍,都是缓冲区中的那一个。而new String()每次都会创建一个新的对象。所以如果之前创建过“xyz”这个对象的话,那么就创建一个对象,而如果之前要是没有创建过这个字符串的话,那么就会创建两个对象。故String str2=“abc”会创建零个或者一个。
String str=“a”+“b”+“c”+“d”+“e”+“f”+“g”+“h”+“i”+“j”+“k”;//创建了几个对象
没错这里仅仅创建了一个对象即str=”abcdefghijk“;这说明javac编译的时候可以对字符串常量直接相加的表达式进行优化,不必等到运行期在进行加法处理,而是在编译的时候直接去掉加号,直接将其编译成这些常量相连的结果。
下面来讲StringBuffer和StringBuilder
对于StringBuffer和StringBuilder是对Stirng的一个优化。之前已经说过了,String对象一旦创建后,String中的内容是不能够改变的。每次改变String都会创建新的对象。这样的话会造成相应空间的浪费。介于此jdk额开发人员计出了StringBuffer和StringBuilder,对于后者而言它们的内容是能够动态改变的。而StringBuffer和StringBuilder的区别就在于StringBuffer是线程安全的(StringBuffer中的绝大部分方法都加了同步关键字)而StringBuilder是线程不安全的。因为StringBuilder是线程不安全的,所以其运行效率会更高,如果一个字符串是在方法里面定义的话,这种情况仅仅可能有一个线程访问它,不存在不安全的因素,这时推荐使用StringBuilder。如果一个实例变量是在类里面定义的,并且在多线程下会访问到,这时最好使用StringBuffer。