String对象的探究
1. 前言(String)
- 内部结构
jdk8
及以前,使用的是char[]
jdk8
以后,使用的是byte[]+字符编码标识
- 不可变性
- 通过字面量的方式给一个字符串赋值,是直接声明在字符串常量池中
- 字符串常量池中是不会存储相同内容的字符串的
- 内存分配
jdk6
及以前:字符串常量池存放在永久代
jdk6
之后:调整到了Java堆
内
intern()
方法jdk6及以前
:如果字符串常量池中有,则不会放入,而是返回已有的字符串常量池中对象的地址;如果没有,会把此对象复制一份(创建一份新的),放入字符串常量池中,并返回字符串常量池中对象的地址jdk6之后
:如果字符串常量池中有,则不会放入,而是返回已有的字符串常量池中对象的地址;如果没有,会把此对象的引用地址复制一份,放入字符串常量池中,并返回字符串常量池中的引用地址
2. new String()到底创建了多少对象(java8举例)?
2.1. new String(“abc”):2/1
- 如果在常量池中
“abc”
不存在,则分别在常量池中和堆中创建“abc”
字符串常量以及字符串实例对象 - 如果在常量池中
“abc”
不存在,则只在字符串实例对象 - 无论如何都会创建字符串实例对象
2.2. String str = “a” + “b” + “c”:1
- 这个
“a + b + c”
在底层会在编译阶段编译为“abc”
,JAVA
在编译器编译时,常量与常量的拼接会得到编译优化为“abc”
并放入常量池中
2.3. String abc =“a”+ new String(“bc”):5
- 这里假设字符串常量池中无数据
- 只要不是单纯的直接使用字符串字面量相加就会在运行时产生一个
StringBuilder
对象用于字符串连接,且不会进行此处的字符串编译优化 - 根据如上图所示,会产生:
StringBuilder
、字符串常量a
、string(”bc“)
、bc字符串常量
、StringBuilder.toString()
方法:会new
一个String(“abc”)
对象,一共五个对象
2.4. String str = new String(“a”) + new String(“b”):6
* 这里假设字符串常量池中无数据
- 根据如上图所示,会产生:
StringBuilder
、string(”a“)
、字符串常量a
、string(”b“)
、b字符串常量
、StringBuilder.toString()
方法:会new
一个String(“ab”)
对象,一共六个对象