梦想还是要有的,万一忘了咋办?

0%

String类型

演进

String对象演进

Java6

  1. char[]、offset、count、hash 四个成员变量。
  2. offset、count 使得String.subString方法可以共享char[]数组,但是存在内存泄漏问题。

思考:

1
2
3
4
JDK1.6
String str1="abc";
String str2=str1.subString(0,1);
这两个对象占多大内存呢?

Java7、8

  1. char[]、hash 2个成员变量
  2. String.substring 方法也不再共享 char[]。

Java9

  1. byte[]、coder、hash 三个成员变量
  2. 改用byte[] 为了节约空间,coder 标识编码方式(0:只包含Latin-1、1:包含UTF-16)

创建&内存位置

2中创建方式:字面量(“abc”)、对象(new String()) ,存储位置有所不同。

  • 字面量创建方式:如果字符串常量池存在直接返回、否则在常量池创建然后返回。
  • 构造方法创建:先在字符串常量池寻找,找到后直接使用,未找到在对象中创建。

字符串常量池

内存位置:方法区-运行时常量池(jdk1.6)、堆-运行时常量池(jdk.7)、堆-元空间(jdk1.8),目前还存在堆内元空间。

特点

  • 共享的:多个对象共用一个真实数据;
  • 不可变:因为一旦变了所有的都会改变;
  • 拼接字符串的性能较差的原因,每次都有创建新的;

比较

“ 当且仅当确定两个对象都在常量池时 可以使用”“进行比较。任何时候都可以使用equals方法进行比较。

intern方法

返回字符串的常量池引用,不存在的话先将对象的字符串引用放入常量池。强制共享对象,使用好了可以降低内存占用。

思考下面代码、为什么?

1
2
3
4
5
6
7
8
9
10
String str1=new String("c")+new String("d");
str1.intern();
String str2="cd";
str1==str2   is True
// ===============================
String str3="ab";
String str4=new String("a")+new String("b");
str4.intern();
str3==str4 is False

编译优化

字符串拼接优化(+),编译后实际使用StringBuilder操作。

1
2
3
4
5
6
7
String str3=new String("c")+new String("d");

编译后:
StringBuilder sb=new StringBuilder();
sb.append(new String("c"));
sb.append(new String("d"));
str3=sb.toString();