JAVA基础:String,StringBuffer,StringBuilder

String
最基础的JAVA类之一,要记住是不可变变类,final class,所有属性也都是final的。对于它的任何改变操作,都会生成新的String对象,影响到应用的性能。

StringBufferStringBuilder
StringBuffer 和StringBuilder要放在一起说。因为这2者都是为了解决或者说优化String对象的拼接等操作导致产生过多的中间变量这个问题而产生的衍生类。二者的内部实现都是可扩充的char数组(JAVA9以后则是byte),只不过StringBuffer是线程安全的(通过每个方法加上synchronized关键字),StringBuilder则不是线程安全的。

JAVA8中字符串拼接底层自动转化为StringBuilder。

字符串缓存:
以JAVA8为例,JVM会把文本字符串以及字符串常量缓存起来,缓存在堆中。也就是说当你再次使用类似“abc”这样的文本字符串时,JVM会直接从缓存中去获取(第一次使用时会存入常量池)。具体的我们可以结合intern()方法来一起感受一下。

intern()方法:intern()用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。否则,在常量池中加入该对象,然后 返回引用。

String s1 = new String("aaa");
String s2 = "aaa";
System.out.println(s1 == s2);    // false

s1 = new String("bbb").intern();
s2 = "bbb";
System.out.println(s1 == s2);    // true

s1 = "ccc";
s2 = "ccc";
System.out.println(s1 == s2);    // true

s1 = new String("ddd").intern();
s2 = new String("ddd").intern();
System.out.println(s1 == s2);    // true

s1 = "ab" + "cd";
s2 = "abcd";    
System.out.println(s1 == s2);    // true

String temp = "hh";
s1 = "a" + temp;
// 如果调用s1.intern 则最终返回true
s2 = "ahh";
System.out.println(s1 == s2);    // false

temp = "hh".intern();
s1 = "a" + temp;
s2 = "ahh";
System.out.println(s1 == s2);    // false

temp = "hh".intern();
s1 = ("a" + temp).intern();
s2 = "ahh";
System.out.println(s1 == s2);    // true

s1 = new String("1");    // 同时会生成堆中的对象 以及常量池中1的对象,但是此时s1是指向堆中的对象的
s1.intern();            // 常量池中的已经存在
s2 = "1";
System.out.println(s1 == s2);    // false

String s3 = new String("1") + new String("1");    // 此时生成了四个对象 常量池中的"1" + 2个堆中的"1" + s3指向的堆中的对象(注此时常量池不会生成"11")
s3.intern();    // jdk1.7之后,常量池不仅仅可以存储对象,还可以存储对象的引用,会直接将s3的地址存储在常量池
String s4 = "11";    // jdk1.7之后,常量池中的地址其实就是s3的地址
System.out.println(s3 == s4); // jdk1.7之前false, jdk1.7之后true

s3 = new String("2") + new String("2");
s4 = "22";        // 常量池中不存在22,所以会新开辟一个存储22对象的常量池地址
s3.intern();    // 常量池22的地址和s3的地址不同
System.out.println(s3 == s4); // false

// 对于什么时候会在常量池存储字符串对象,我想我们可以基本得出结论: 1. 显示调用String的intern方法的时候; 2. 直接声明字符串字面常量的时候,例如: String a = "aaa";
// 3. 字符串直接常量相加的时候,例如: String c = "aa" + "bb";  其中的aa/bb只要有任何一个不是字符串字面常量形式,都不会在常量池生成"aabb". 且此时jvm做了优化,不//   会同时生成"aa"和"bb"在字符串常量池中

摘录自:https://www.cnblogs.com/Kidezyq/p/8040338.html

字符串在JAVA9中的变化:
实现从char[] 变为了byte[],并加上一个标识编码的所谓 coder,具体可自行参见源码。这一点改变带来的影响就是:更小的内存占用、更快的操作速度。同时能够保存的字符串最大长度缩减为原先的一半。

你可能感兴趣的:(JAVA基础)