String及其工具类
String 类
String 字符串特性
- final 类,不可被继承
- 实现 Serializable 接口,支持序列化
- 实现 Comparable 接口,可比较大小
- 内部使用 final char 数组存储字符串数据,解释类 String 不可更改原因
- String 具有不变性,体现:
- 字面量赋值,字符串值存储在字符串常量池中(常量池不会存储相同内容字符串)
- 对字符串进行修改(replace)或者是拼接(StringBuilder、StringBuffer、直接+)字符串时,不会修改原值,而是新建一个值,在新值上修改或拼接
1 | public static void main(String[] args) { |
String 字面量赋值和构造器赋值区别
使用构造器的变量指向的地址是堆中的地址,堆再指向 abc
字面量变量地址指向的是 abc
字符串常量池中不会存在两个相同的字符串

String 和基本数据类型、包装类之间转换
String 转包装类、基本数据类型
调用对应包装类的 parseXxx(Str)方法
包装类、基本数据类型转 String
调用 String 类的 valueOf();
面试题:
构造器创建的字符串在内存中创建了几个对象?
最多两个,如果字符串常量池中存在该字符串,则只在堆中创建一个空间,存放字符串常量池中对应字符串的地址!!!
String 陷阱
String s1 = “a”;
说明:在字符串常量池中创建了一个字面量为“a”的字符串。
s1 = s1 + “b”;
说明:实际上原来的“a”字符串对象已经丢弃了,现在在堆空间中产生了一个字符
串s1+”b”(也就是“ab”)。如果多次执行这些改变串内容的操作,会导致大量副本
字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响
程序的性能。
String s2 = “ab”;
说明:直接在字符串常量池中创建一个字面量为”ab”的字符串。 String s3 = “a” + “b”;
说明:s3指向字符串常量池中已经创建的“ab”的字符串。
String s4 = s1.intern();
说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在的“ab”字符串
赋值给 s4。
1 | String s9="hello"; |
总结:
- 常量与常量的拼接修改结果存在常量池中,且不会存在相同内容的常量
- 只要是变量的拼接或修改,地址为堆中的地址。
- 调用 intern 返回的是常量池中存在的地址
StringBuffer 和 StringBuilder 类
三者异同点
String:不可变字符串序列
StringBuffer:线程安全,效率低,可变字符串序列
StringBuilder:线程不安全,效率高,可变字符串序列 jdk5 新增
原因:append 方法是否被 synchronized 修饰
源码分析
StringBuffer sb1=new StringBuffer();//底层创建一个长度为 16 的 char 数组
sb1.append(‘a’);//value[0]=a;
sb1.length()//等于数组实际存储的字符数,不等于数组长度
扩容流程
- 调用 append 方法,
- 调用父类的 append 方法
- 调用 ensureCapacityInternal,确保数组长度够用
- 如果不够用进行数组长度*2+2,再调用 arraysCopy 的方法将原有数组复制到新数组中





