任何字符串都是String的子类
字符串是不变的; 它们的值在创建后无法更改。 字符串缓冲区支持可变字符串。 因为String对象是不可变的,所以可以共享它们。
如何理解共享?当创建的两个字符串内容相同,则程序内部就会使用同一个内存地址存储字符串,如果使用了new那么就是两个不同的空间
相当于:字符数组,由于是一个数组来存储字符串,所以字符串确定后,字符串就是不变的了
char data[] = {'a', 'b', 'c'};
String str = new String(data);
字符串常量池
堆 在逻辑上分为三个部分:
新生代
老年代
永久代:不进行垃圾回收,常驻内存。字符串就存储在这,类的信息,接口的信息也存储在这
创建的新的对象是存储在新生代中的,因为有些对象创建之后就可能只用一次,后面就直接不用了。新生代的GC机制是不一样的,它会频繁的进行垃圾回收。
当一个对象进行了15次垃圾回收还没有被回收掉就会进入老年代
新生代还有细分为 Eden区和Survior区
Eden : 新创建的对象
Survior 0/1:经过垃圾回收,但是垃圾回收次数小于15次
jdk1.7之前运行时常量池(包括字符串常量池)存放在方法区
jdk1.7 字符串常量池 被从方法区拿到了堆中
jdk 1.8移除了 永久代,用元空间(Metaspace)代替
通过 + 进行 字符串的拼接 是消耗内存空间的,会产生垃圾,能避免就避免。因为字符串存储在永久代的,产生的垃圾也无法被回收。String是定长的字符串,每一次的拼接在栈中就会开辟新的空间存储字符串的拼接结果
如果非要进行字符串的拼接,建议使用StringBuffer 和 StringBuilder
区别:String是定长字符序列,StringBuffer 和 StringBuilder是可变字符序列
先StringBuffer ab = new StringBuffer(),初始容量是16
使用append方法添加数据: sb.append("11")
最后使用sb.toString()就可以得到拼接之后的字符串