String常量池和堆区介绍:String、StringBuilder与StringBuffer的区别?
常量池和堆区
简单介绍
简单的来说: 类中使用 final 关键字修饰字符数组来保存字符串, final char value ,所以 对象是不可变的。 而 与 都继承自 r 类,在 r 中也是使用字符数组保存字符串 但是没有用 final 关键字 修饰,所以这两种对象都是可变的。 与 的构造方法都是调用父类构造方法也就是 r 实现的。
r.java
线程安全性
中的对象是不可变的,也就可以理解为常量,线程安全。 r 是 与 的公共父类,定义了一些字符串的基本操作,如 、 、 、 等公共方法。 对方法加了同步锁或 者对调用的方法加了同步锁,所以是线程安全的。 并没有对方法进行加同步锁,所以 是非线程安全的。
性能
每次对 类型进行改变的时候,都会生成一个新的 对象,然后将指针指向新的 对象。 每次都会对 对象本身进行操作,而不是生成新的对象 并改变对象引用。相同情况下使用 相比使用 仅能获得 10%~15% 左 右的性能提升,但却要冒多线程不安全的风险。 对于三者使用的总结:
操作少量的数据: 适用 单线程操作字符串缓冲区下操作大量数据: 适用 多线程操作字符串缓冲区下操作大量数据: 适用 代码分析

public class Str1 {
public static void main(String[] args) {
//直接引号赋值
String str1="abc";
String str2="abc";
System.out.println(str1==str2);//true
//通过new创建对象
String str3="abc";
String str4=new String("abc");
System.out.println(str3==str4);//false
String str5=new String("abc");
String str6=new String("abc");

System.out.println(str5==str6);//false
}
}
采用引号赋值创建一个字符串时,JVM首先会在常量池中找有没有这个对象,没有则在常量池中创建这个对象"abc",然后把字符串对象的引用地址返回给字符串常量str1有则不再创建新的对象,直接把字符串对象的引用地址返回给字符串常量str2因此.out.(str1==str2);//true输出为true 采用new创建对象,JVM则在堆区创建"abc"对象,然后将对象的地址返回赋给str4引用每一次new都会在堆区创建一个新的"abc"对象
/*
* 首先在常量池创建一个"abcdef"的对象,并返回给str7
* "abc"+"def"会先实现拼接,然后再到常量池中找"abcdef"
* str7和str8都会指向同一个"abcdef"对象,两者的地址相同
*/
String str7="abcdef";
String str8="abc"+"def";
System.out.println(str7==str8);//true
String s1="a";
String s2=s1+"b";
/*String s2=s1+"b";
* 等价于
* StringBuffer tempBuffer=new StringBuffer();
tempBuffer.append("a");
tempBuffer.append("b");
String s2=tempBuffer.toString();
*/
System.out.println(s1==s2);//false
























