String 类
基本介绍
- String 对象用于保存字符串,也就是一些字符序列
- 字符串常量对象使用双引号括起来的字符对象,如“Jack”、“你好”等
- 字符串的字符采用 Unicode 编码,一个字符(不论是字符还汉字)占两个字节
- String 类有很多构造方法,如以下常用的几个:
-
String s1 = new String();
-
String s2 = new String(String original);
-
String s3 = new String(char[] a);
-
String s4 = new String(char[] a, int startIndex, int count);
-
String s5 = new String(byte[] b);
-
- String 类实现了接口 Serializable ,所以 String 可以串行化(串行化的作用就是 String 可以在网络传播)
- String 类实现了接口 Comparable ,所以 String 可以比较大小
- String 是 final 类,所以不能被其他的类继承
- String 类里有一个属性: private final char value[] 用于存放字符串内容(传递过来的字符串都放在 value 数组中), value 是用 final 修饰的,即 value 是一个常量,不可以修改(value 是一个数组,所以不可修改是指 value 的地址不可以修改,即 value 不可以再指向一个新的地址,但是数组的内容可以修改,即数组元素可以修改)
public class Test {
public static void main(String[] args) {
final char[] value = {'a','b','c'};
value[0] = 'q'; // 数组元素可以修改
char[] v = {'1','2','3'};
// value = v; // 报错,数组的地址不能修改,即不能指向一个新的对象(地址)
}
}
创建 String 对象的两种方式和区别
1、直接赋值 String s = "zs";
- 先从常量池查看是否有 "zs" 数据空间,如果有,直接让 s 指向该数据空间,如果没有则重新创建,然后让 s 指向创建的空间。 s 最终指向的是常量池的空间地址
2、调用构造器 String s2 = new String("zs");
- 先在堆中创建空间,里面维护了 value 属性,指向常量池的 "zs" 空间。如果常量池没有 "zs" ,就重新创建,如果有,直接通过 value 指向。s2 最终指向的是堆中的空间地址
内存分析图如下
字符串的特性
- String 类是 final 类,代表不可变的字符序列
- 字符串是不可变的,一个字符串对象一旦被分配,其内容不可更改
例题1:以下语句创建了几个对象?
String s = "hello";
s = "haha";
答案:两个,内存示意图如下
例题2:以下语句创建了几个对象?
String s = "abc" + "def";
答案:一个,因为编译器会进行优化,判断创建的常量池对象是否有引用指向
String s = "abc" + "def"; 会优化成 ——> String s = "abcdef";
所以最终只创建了 “abcdef” 这一个对象
例题3:
String a = "hello";
String b = "abc";
/*
* 根据 debug 的过程可以得到如下 String c = a + b 语句的执行流程
* 1、首先创建一个对象 StringBuilder sb = new StringBuilder();
* 2、然后在 sb 对象里追加 a 和 b 对应的字符串
* sb.append("hello");
* sb.append("abc");
* 3、最后根据 sb 对象生成一个 String 对象: String c = sb.toString();
* public String toString(){ // StringBuilder 里的 toString 方法源码
* // value 存储的是 hello abc 字符序列
return new String(value, 0, count);
}
* 所以最后 c 其实指向的是堆中的 String 对象, String 对象里的 value[] 指向常量池中的 ”helloabc“
*/
String c = a + b;
内存分析图如下
StringBuffer 类
基本介绍
StringBuffer 代表可变的字符序列,可以对字符串内容进行增删。StringBuffer 中的很多方法和 String 相同,但 StringBuffer 是可变长度的。 StringBuffer 是一个容器。
- StringBuffer 的直接父类是 AbstractStringBuilder,StringBuffer 实现了接口 Serializable ,即 StringBuffer 的对象可以串行化
- 在父类 AbstractStringBuilder 中有属性 char[] value ,value 不是 final 修饰的,存放字符串内容,所以 StringBuffer 字符串是可变的,并且不是放在常量池中,而是放在堆中(因为 value 不是 final 常量)
- StringBuffer 是一个 final 类,不能被继承
String VS StringBuffer
- String 保存的是字符串常量(放在常量池中),里面的值不能更改(因为 value 属性是一个 final 数组: private final char value[]),每次 String 类的更新实际上就是更改地址,效率较低。
- StringBuffer 保存的是字符串变量(放在堆中),里面的值可以更改,每次 StringBuffer 的更新实际上是更新内容(因为 value 没有用 final 修饰: char value[]),不用每次更新地址(除非是内存空间不够了才会重新开辟更大的空间来存储原有的内容),效率较高。
StringBuffer 构造器
public class Test {
public static void main(String[] args) {
// 由源码可知,创建了一个大小为 16 的 char[] ,用于存放字符序列
StringBuffer s1 = new StringBuffer();
// 由源码可知,创建了一个大小为 100 的 char[]
StringBuffer s2 = new StringBuffer(100);
// 由源码可知,创建了一个大小为 str.length + 16 的 char[]
// 如以下创建了 5 + 16 = 21 的char[]
StringBuffer s3 = new StringBuffer("hello");
}
}
String 和 StringBuffer 的相互转换
public class Test {
public static void main(String[] args) {
// String -> StringBuffer
String str = "hello";
// 方式一:构造器
StringBuffer s1Buffer = new StringBuffer(str);
// 方式二: append() 方法
StringBuffer s2Buffer = new StringBuffer();
s2Buffer = s2Buffer.append(str);
// StringBuffer -> String
StringBuffer s3Buffer = new StringBuffer("world");
// 方式一:使用 toString 方法
String str1 = s3Buffer.toString();
// 方式二:使用构造器
String str2 = new String(s3Buffer);
}
}
StringBuffer 的常用方法(一小部分)
- 增: append
- 删: delete
- 改: replace
- 查: indexOf
- 插入: insert
- 获取长度: length
这些方法的具体使用可以参考: 视频链接
StringBuilder 类
基本介绍
StringBuilder 是一个可变的字符序列,StringBuilder 类提供一个与 StringBuffer 兼容的 API (即 StringBuffer 类有的 API ,StringBuilder 都有),但不保证同步(StringBuilder 不是线程安全的)。 StringBuilder 类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(单个线程时不存在线程安全问题),如果是在单线程的情况下,建议优先采用 StringBuilder 类,因为在大多数实现中,它比 StringBuffer 更快
在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。
StringBuilder 和 StringBuffer 均代表可变的字符序列,方法是一样的,所以使用和 StringBuffer 一样
继承体系图如下:
String 、 StringBuffer 、 StringBuilder 的比较