Dawn's Blogs

分享技术 记录成长

0%

Java高级 (2) 常用类之字符串相关类

String 类

String 是一个 final 类,表示一个不可变的字符串。

String 对象的字符内容是存储在一个字符数组 value[] 中的。

  • String 实现了三个接口:
    • Serializable 接口:表示字符串是可序列化的。
    • Comparable 接口:字符串可以比较大小。
    • CharSequence 接口:字符串实际上是字符数组序列。
1
2
3
4
5
6
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0

字符串存储结构

实例化字符串

  • 当字符串以字面量(直接赋值)的方式声明一个字符串时,字符串常量直接存储在常量池中。

  • 以 new 的方式声明一个字符串时,字符串中非常量对象存储在中,对象中的 value 数组指向常量池。

String str1 = "abc";String str2 = new String("abc"); 的内存存储区别如下:

image-20230130105516940

1
2
3
4
5
6
7
8
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = new String("abc");

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s3 == s4); // false

字符串拼接

字符串拼接时:

  • 常量与常量的拼接,结果在常量池中。
  • 只要其中有一个是变量,结果就在中(相当于 new 一个 String 对象)。
  • String 的 intern 方法返回常量池中的字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String s1 = "Hello";
String s2 = "World";

String s3 = "HelloWorld";
String s4 = "Hello" + "World";
String s5 = s1 + "World";
String s6 = "Hello" + s2;
String s7 = s1 + s2;
String s8 = (s1 + s2).intern();

System.out.println(s3 == s4); // true
System.out.println(s3 == s5); // false
System.out.println(s3 == s7); // false
System.out.println(s5 == s6); // false
System.out.println(s5 == s7); // false
System.out.println(s3 == s8); // true

StringBuffer 和 StringBuilder

StringBuffer 类

java.lang.StringBuffer 代表可变的字符序列

image-20230130142840119

构造器

StringBuffer 对象创建必须使用构造器,有三个构造器:

  • StringBuffer():初始容量为 16 的字符串缓冲区。
  • StringBuffer(int size):构造指定容量的字符串缓冲区。
  • StringBuffer(String str):将内容初始化为指定字符串内容,底层数组为字符串长度+16。

扩容

当添加的元素底层数组存放不下,就需要扩容。

  • 默认情况下,扩容为原来的 2 倍 + 2。
  • 若容量还是不够,将拼接后的长度当作扩容容量。
1
2
3
4
5
6
7
8
9
10
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2; // 默认情况下
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity; // 将拼接后的长度当作扩容容量
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}

StringBuilder 类

StringBuilder 也代表可变的字符序列,而且与 StringBuffer 提供的相关方法一样。

对比 String、StringBuffer、StringBuilder:

  • String(JDK 1.0):不可变字符序列。
  • StringBuffer(JDK 1.0):可变字符序列,效率低、线程安全
  • StringBuilder(JDK 5.0):可变字符序列,效率高、线程不安全