一、字符串基本知识
1.String对象的创建
直接创建一个常量String对象,结果如下: 创建常量字符串和创建字符串对象的区别,如下图: 实际上,字符串常量存储在字符串常量池,目的是为了共享;而字符串非常量对象存储在堆中。 s1和s2都是常量字符串,用等号比较直接比的都是值。 s3和s4都是字符串对象,即使它们的值相等,但是地址不一样,所以等号为false
2.字符串的特性
常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。 只要其中一个是变量,结果就在堆中。 如果拼接的结果调用intern方法,返回值就在常量池中。
3.字符串相关方法
方法 | 说明 |
---|
char charAt(int index) | 返回某索引处的字符return value[index] | boolean isEmpty() | 判断是否是空字符串:return value.length == 0 | String toLowerCase() | 将 String 中的所有字符转换为小写 | String toUpperCase() | 将 String 中的所有字符转换为大写 | String trim() | 返回字符串的副本,忽略前导空白和尾部空白 | int compareTo(String anotherString) | 比较两个字符串的大小 | String substring(int beginIndex) | 返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串 | String substring(int beginIndex, int endIndex) | 返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串 | boolean endsWith(String suffix) | 测试此字符串是否以指定的后缀结束 | boolean startsWith(String prefix) | 测试此字符串是否以指定的前缀开始 | boolean startsWith(String prefix, int toffset) | 测试此字符串从指定索引开始的子字符串是否以指定前缀开始 | int indexOf(String str) | 返回指定子字符串在此字符串中第一次出现处的索引 | int indexOf(String str, int fromIndex) | 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始 | int lastIndexOf(String str) | 返回指定子字符串在此字符串中最右边出现处的索引 | int lastIndexOf(String str, int fromIndex) | 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索 | String replace(char oldChar, char newChar) | 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的 | String replaceAll(String regex, String replacement) | 使 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串 | String replaceFirst(String regex, String replacement) | 使 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串 | String[] split(String regex) | 根据给定正则表达式的匹配拆分此字符串 |
4.String与基本数据类型的转换
1)字符串转换为基本数据类型或包装类: public static int parseInt(String s) 2)基本数据类型转换为字符串: 调用String类的public String valueOf(int n) 可将int型转换为字符串 3)字符数组转换为字符串: String 类的构造器:String(char[]) 和 String(char[],int offset,int length) ,分别用字符数组中的全部字符和部分字符创建字符串对象。 4)字符串转换为字符数组: public char[] toCharArray() :将字符串中的全部字符存放在一个字符数组中的方法 public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) :提供了将指定索引范围内的字符串存放到数组中的方法 5)字节数组转换为字符串: String(byte[]) :通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String 6)字符串转换为字节数组: public byte[] getBytes() :使用平台的默认字符集将此 String 编码为byte 序列,并将结果存储到一个新的 byte 数组中 public byte[] getBytes(String charsetName) :使用指定的字符集将 此 String 编码到 byte 序列,并将结果存储到新的 byte 数组
二、字符串相关的类
1.StringBuffer类
1.1 StringBuffer类介绍
java.lang.StringBuffer代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象 它的底层代码:
1.2 StringBuffer类创建
StringBuffer类必须用构造器生成,它有三个构造器:
构造器 | 说明 |
---|
StringBuffer() | 初始容量为16的字符串缓冲区 | StringBuffer(int size) | 构造指定容量的字符串缓冲区 | StringBuffer(String str) | 将内容初始化为指定字符串内容,此时容量为字符串长度+16 |
1.3 StringBuffer类常用方法
方法 | 说明 |
---|
StringBuffer append(xxx) | 用于进行字符串拼接 | StringBuffer delete(int start,int end) | 删除指定位置的内容 | StringBuffer replace(int start, int end, String str) | 把[start,end)位置替换为str | StringBuffer insert(int offset, xxx) | 在指定位置插入xxx | StringBuffer reverse() | 把当前字符序列逆转 |
在使用append和insert方法时,如果原来value数组长度不够,可以扩容
2.StringBuilder类
2.1 StringBuilder类介绍
StringBuilder和StringBuffer很相似,也是可变的字符序列,功能也一样。
3.String、StringBuffer和StringBuilder对比
String:不可变字符序列 StringBuffer:可变字符序列、效率低、线程安全(扩容方法中有关键字synchronized) StringBuilder:可变字符序列、效率高、线程不安全(扩容方法没有关键字synchronized)
扩容问题: 如果要添加的数据底层数组存储不下了,就需要扩容底层的数组。 默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中;如果容量还不够,直接选取需要的容量大小作为新的容量。
开发建议: 在需要多次修改字符串的情况下,String效率最低,不建议使用;建议使用StringBuffer(int capacity)或StringBuilder(int capacity)方法,考虑线程安全问题选取。
StringBuilder线程不安全原因: StringBuilder里的成员变量:
char[] value;
int count;
StringBuilder中的方法是没有synchronized这个关键字的,它的append方法中的count+=len 导致了线程不安全,当多个线程都要使用append进行添加字符串时,count会增加,如果被同时读取到一个值,那么改变后的结果就不正确了:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
在后面调用getChars时,因为count不正确,所以可能发生越界异常的情况。
|