根据网课做的记录,有几句是自己的理解,如有错误,敬请指正
首先,要知道这样几个小知识:不考虑线程,单从效率上讲,StringBuilder 比 “ + ” 更高效!
1、方法区(永久代”、“非堆区”)
- 被所有线程共享。
- 所有定义的方法的信息都存在该区域,包括静态变量、常量、类信息(构造方法、接口定义)、运行时常量池。
- 实际变量存在堆内存,与方法区无关
- 以上为逻辑上的定义,HotSpot中,方法区仅逻辑独立,实际上包含在JAV堆中,即,物理上属于JAVA堆区的一部分,永久区是方法区的实现
2、一个JVM实例只存在一个堆内容,堆在逻辑上分新生代、老年代、永久代
- 新生区:新创建的对象,垃圾回收次数 < 15次的对象
- 老年区:位于堆空间,垃圾回收次数 > 15次,还依然存活的对象
- 永久区:位于非堆空间,常驻内存区域,存放JDK自身携带的 Class、Interface 的元数据,即运行环境必须存储的类信息,一旦到了这个区域,就不会被回收掉,除非关闭JVM才会释放该区域所占的内存。
3、演变进程
- JDK1.7之前,hotspot虚拟机堆方法区的实现为永久代,运行常量池(含字符串常量池)存放在方法区。
- JDK1.7,字符串常量池拿到了堆中,运行常量池剩余的部分还在方法区(即永久代)。
- JDK1.8及之后,用“元空间”(metaspace)取代了“永久代”;字符串常量池还在堆中,运行常量池还在方法区,只是方法区的实现从“永久代”变成了“元空间”。
4、字符串是不变的,创建后无法更改。字符串缓冲区支持可变字符串,可以共享。比如:
如果用 “ + ” 拼接,如下,输出结果必然是 abcdefghi
String text1 = "abc"; String text2 = "def"; String text3 = "ghi"; String text4 = text1 + text2 + text3; System.out.println(text4);
text1、text2、text3在堆中分别占有三段内存
用 “+” 拼接时,分别会形成这样两段字符 “abcdef” 、 “abcdefghi”
这两段字符都会存放在堆中(字符串常量池),各自再占一块内存,如果后面不用到“abcdef”,它也不会被回收。
StringBuilder拼接字符串的主要写法如果在进行大数据分析做数据采集时,大量用到 “+” 拼接,那么造成的内存垃圾可想而知,数据一旦变大,运行时间一长,必然导致卡顿。所以说它低效。用 StringBuilder 就可以避免这个问题。
StringBuilder sb = new StringBuilder();
sb.append("1");
sb.append("2");
sb.append("3");
String text = sb.toString();
System.out.println(text);
输出结果如下



