X

浅谈Java中字符串的初始化及字符串操作类

在深入学习字符串类之前, 我们先搞懂JVM是怎样处理新生字符串的. 当你知道字符串的初始化细节后, 再去写String s = “hello”或String s = new String(“hello”)等代码时, 就能做到心中有数。

首先得搞懂字符串常量池的概念。

常量池是Java的一项技术, 八种基础数据类型除了float和double都实现了常量池技术. 这项技术从字面上是很好理解的: 把经常用到的数据存放在某块内存中, 避免频繁的数据创建与销毁, 实现数据共享, 提高系统性能。

字符串常量池是Java常量池技术的一种实现, 在近代的JDK版本中(1.7后), 字符串常量池被实现在Java堆内存中。

下面通过三行代码让大家对字符串常量池建立初步认识:

public static void main(String[] args) {
String s1 = “hello”;
String s2 = new String(“hello”);
System.out.println(s1 == s2); //false
}

我们先来看看第一行代码String s1 = “hello”;干了什么.

当我们使用new关键字创建字符串对象的时候, JVM将不会查询字符串常量池, 它将会直接在堆内存中创建一个字符串对象, 并返回给所属变量。

所以s1和s2指向的是两个完全不同的对象, 判断s1 == s2的时候会返回false。

如果上面的知识理解起来没有问题的话, 下面看些难点的.

public static void main(String[] args) {
String s1 = new String(“hello “) + new String(“world”);
s1.intern();
String s2 = “hello world”;
System.out.println(s1 == s2); //true
}

第一行代码String s1 = new String(“hello “) + new String(“world”);的执行过程是这样子的:

1.依次在堆内存中创建”hello “和”world”两个字符串对象

2.然后把它们拼接起来 (底层使用StringBuilder实现, 后面会带大家读反编译代码)

3.在拼接完成后会产生新的”hello world”对象, 这时变量s1指向新对象”hello world”

执行完第一行代码后, 内存是这样子的:

第三行代码String s2 = “hello world”;

这种直接通过双引号”“声明字符串背后的运行机制我们在第一个案例提到过, 这里正好复习一下。

首先虚拟机会去检查字符串常量池, 发现有指向”hello world”的引用. 然后把该引用所指向的字符串直接返回给所属变量。

执行完第三行代码后, 内存示意图如下: