① 概念
String属于引用数据类型,被final修饰,不可被继承改变
② String的内存模型
String s = "abc";
在编译期会检查pool中是否有"abc"对象,如果有则返回pool中对象地址,否则在pool中创建"abc"对象并返回地址
String s = new String("abc");
同样在编译期会判断pool中是否有"abc"对象,如果没有会在pool中新建一个,然后copy一个副本到heap area 中
③ 关于常量池
- 理解常量池:类似一个JVM级别的缓存
- 位置:JDK1.7之前String Pool处于Method area,1.7开始移到了Heap中
- 原理:String Pool 底层是一个固定大小的Hashtable,默认长度为1009(可通过JVM参数
-XX:StringTableSize=1009
来跟改),放入的String很多是会导致Hash冲突严重,从而导致链表过长,影响性能
④ 关于intern()
- intern作用:将字符串缓存到常量池
- 原理:如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回
- 注意:JDK1.7开始,StringPool移到Heap Area中调用intern不会再在String中创建新的对象,而是保存Heap中Object的引用
- intern使用:当新建的String对象达到一定数量,会在Heap,StringPool中创建很多对象占用空间也随之变大,此时使用Intern()缓存到StringPool可以减少大量对象占用空间,但是值的注意的是,StringPool是有大小的当过多使用intern导致StringPool链表过长时反而会得不偿失
⑤ String常用方法
- 字符串长度:
int length()
- 子串截取【含头不含尾】:
String substring(int beginIndex, int endIndex) / String substring(int Index)
- 忽略大小比较:
boolean equalsIgnoreCase(String anotherString)
- 拼接字符串:
String concat(String str)
- 首次出现的位置:
int indexOf(int ch/String str, int fromIndex)
- 最后出现的位置[从后面开始遍历]:
int lastIndexOf(int ch/String str, int fromIndex)
- 指定位置的字符:
char charAt(int index)
- 大小写转换:
String toLowerCase() / String toUpperCase()
- 替换:
String replace(char oldChar, char newChar) / String replaceFirst(String regex, String replacement) / String replaceAll(String regex, String replacement)
- 去空格:
trim()
- 匹配开始结束位置:
boolean statWith(String prefix) / boolean endWith(String suffix)
- 判断是否包含:
boolean contains(String str)
- 字符串分解:
String[] split(String str)
- 其它基本类型转String:
static String valueOf()
- String转其他类型:
static xx parseXX(String str)
- 字典大小比较:
int compareToIgnore(String anotherString)
- 格式化:
String.format("a%sc%sd", b, d)
⑥ StringBuilder、StringBuffer
- StringBuilder,StringBuffer是可变的
- StringBuilder是非线程安全的,StringBuffer 是线程安全的
- StringBuilder默认缓冲16,即使是
new StringBuilder("test")
也会在字符串长度之外再另外缓冲16 - 扩容:当append的字符长度超过缓冲长度后,则扩容为原来字节数组的长度*2+2,如若还不够则直接扩容到当前必要最小长度
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时,最好要考虑初始化一下缓冲大小,较少扩容的次数,提高效率。
参考文献:美团技术博客