String类的常用方法
equals // 区分大小写,判断内容是否相等
equalsIgnoreCase //忽略大小写的判断内容是否相等
length // 获取字符的个数,字符串的长度
indexOf //获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
lastIndexOf //获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1
substring //截取指定范围的子串
trim //去前后空格
charAt:获取某索引处的字符, 注意不能使用Str[index] 这种方式
toUpperCase // 字符串转大写
toLowerCase // 字符串转小写
concat // 拼接字符串
replace //替换字符串中的字符
split //分割字符串
compareTo //比较两个字符串的大小
toCharArray //转换成字符数组
format //格式字符串, %s 字符串 %c 字符 %d 整型 %.2f 浮点型
随用随查,其实最好每个都用一遍,但我为了效率,只读了一遍定义,后面用到再说
StringBuffer类
StringBuffer 也是一个容器。它的很多方法都和 String 相同,但与 String 最大的区别在于它是可变长度的。
-
String 类实际上保存的是字符串常量,内部的值不能修改。每次 String 类的更新,实际上就是在更改地址,效率较低。
- private final byte[] value;
-
StringBuffer 保存的是字符串变量,里面的值可以更改。每次 StringBuffer 的更新,实际上是更新内容,并不用每次更新地址,效率较高。
- byte[] value;
此外,StringBuffer还有如下要点
1. StringBuffer的直接父类是 AbstractStringBuilder
2. StringBuffer实现了 Serializable ,即StringBuffer的对象可以串行化
3. 在父类 AbstractStringBuilder 中有属性byte[] value,不是fianl的,可以修改
4. StringBuffer是个final类,不能被继承
StringBuffer的初始化、和String的相互转化
// 初始化
// 第一种方法,创造一个大小为 16 的 byte 数组
StringBuffer sb = new StringBuffer();
// 第二种方法,创造一个指定大小的 byte 数组
StringBuffer sb2 = new StringBuffer(100);
// 第三种方法,创造一个字符串对应的 byte 数组
StringBuffer sb3 = new StringBuffer("hello");
// String -> StringBuffer
// 方式1:使用构造器
String str = "hello";
StringBuffer sb4 = new StringBuffer(str);
// 方式2:使用append()
StringBuffer sb5 = new StringBuffer().append(str);
// StringBuffer -> String
// 方式1:使用toString()
String str2 = sb5.toString();
// 方式2:使用构造器
String str3 = new String(sb5);
StringBuffer的常用方法
-
增:
append -
删:
delete(start, end) -
改:
replace(start, end, string)
// 将start到end之间的内容替换掉,不含end -
查:
indexOf
// 查找子串在字符串中第1次出现的索引,如果找不到返回-1 -
插:
insert -
获取长度:
length
小练习
第一题
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(sb.length());
System.out.println(sb);
StringBuffer sb1 = new StringBuffer(str);
System.out.println(sb1);
答案:
4
null
空指针异常
解析:
这道题的解决方法是去读源码:StringBuffer 的 append 方法执行到最后,它会有一个检查。如果传进来的字符串是 null 的话,它会执行一个叫 appendNull 的方法。就是直接把 null 看作 "null"字符串,因此第一个输出是 4,第二个是 null
new StringBuffer(str)点进去看源码,会走到int length = str.length();这步,那就没得说了,对着 null 访问length方法,肯定会保空指针异常。
StringBuilder
基本介绍:
StringBuilder 是一个可变的字符序列。这个类提供一个和 StringBuffer 兼容的 API,但是不保证同步。
StringBuilder 不是线程安全的。这个类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单线程使用的时候。如果可能,单线程优先采用此类,它比 StringBuffer 速度要快。
StreamBuilder 上的主要方法是 append 和 insert。可以重载这些方法,使它们接受任意数据。
1. StringBuilder的直接父类是 AbstractStringBuilder
2. StringBuilder实现了 Serializable ,即StringBuilder的对象可以串行化
3. 在父类 AbstractStringBuilder 中有属性byte[] value,不是fianl的,可以修改
4. StringBuilder是个final类,不能被继承
5. StringBuilder 没有做互斥处理,但是最为高效,因此在单线程的场景下使用
对比
我们比较一下 String、StringBuffer 和 StringBuilder:
-
StringBuilder 和 StringBuffer 非常类似,它们都代表可变的字符序列,而且方法也类似。
-
String 是不可变的字符序列,效率低,但是复用率很高。
-
StringBuffer 是可变的字符序列,它在增删上效率较高,而且它是线程安全的。
-
StringBuilder 也是可变的字符序列,它的效率最高,但它的线程不安全。
-
String 的使用注意说明:
String s = “a” 本质是创建一个字符串,但如果 s += “b” 的话,它就会把原来的 “a” 字符串丢弃,产生一个新的字符串 “ab”。如果多次执行这些改变字符串内容的操作,会导致大量的文本串留在内存中,降低效率。如果这样的操作放到循环中,会极大地影响程序的性能。结论是:如果我们需要对字符串做大量的修改,就不要使用 String。
最终结论:
如果字符串存在大量的修改操作:
-
且是单线程,就使用 StringBuilder
-
或者是多线程,就使用 StringBuffer
假如字符串很少修改,且被多个对象引用,则使用 String