String
String不可变
对象的不可变性是指对象本身的属性或者说本身的数据不会改变
public final class String{
private final byte[] value; }
1.底层是被final修饰的字符数组,保证了其不可指向新的数组
2.还被private修饰,并且String没有暴露和提供任何修改字符数组的方法
3.String类换被final修饰了,其不可被继承,杜绝了其子类覆盖父类行为的可能
一些字符串操作都是返回新的String对象,绝对不会影响原数据。获取其底层字符串数组时,也是复制一个新数组进行返回,原数组也不会受到影响
为什么这么设计
- 只有String不可变,字符串常量池才能发挥作用。
- 用字面量创建字符串时,字符串常量池会返回已有对象的引用,如果字符串可变,那引用的值随时可以修改,并且随时能影响其他的引用,从而数据会发生各种错误,这样常量池谈何复用
- 换可以保证其哈希码也不会变,因此计算一次哈希码以后,就可以将其缓存,下次用到时就无需计算了,性能更高。
- 所以可以放心使用和哈希计算相关的对象,比如HaseMap,HaseSet,如果String的哈希码会改变,那就会影响这些对象的哈希计算,从而导致预期之外的结果
- 不可变对象,线程安全
可以用反射来改变String中的value的值,所以严格意义上不一定不可变
String ,StringBuffer StringBuilder
String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象。
StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
String | 不可变 | 线程安全 | 操作少量数据或不需要操作数据 |
---|---|---|---|
StringBuffer | 可变 | 线程安全,性能低 | 多线程使用共享变量 |
StringBuilder | 可变 | 线程不安全 | 优先使用 |
StringBuffer 为什么是线程安全的
StringBuffer给方法添加了同步锁 synchronized 。
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须 获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法 返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。
线程安全
多线程下每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的
字符串拼接
1.StringBuffer/StringBuilder.append(","); ------- a,b,c,
2.StringJoiner(",","{","}"); {a,b,c}
3.StringUtils.join();
4.String.join();
String有哪些常用的方法
boolean equals(Object obj) 判断两个字符串中的内容是否相同。
boolean equalsIgnoreCase(String str) 判断两个字符串中的内容是否相同, 忽略大小写。
boolean contains(String str) 判断该字符串中 是否包含给定的字符串。
boolean startsWith(String str) 判断该字符串 是否以给定的字符串开头。
boolean endsWith(String str) 判断该字符串 是否以给定的字符串结尾。
boolean isEmpty() 判断该字符串的内容是否为空的字符串 ""
int length() 获取该字符串的长度。
char charAt(int index) 获取该字符串中指定位置上的字符。
String substring(int start) 从指定位置开始,到末尾结束,截取该字符串,返回新字符串。
String substring(int start,int end) 从指定位置开始,到指定位置结束,截取该字符串,返回新字符串。
int indexOf(int ch ) 获取给定的字符,在该字符串中第一次出现的位置。
int indexOf(String str) 获取给定的字符串,在该字符串中第一次出现的位置。
byte[] getBytes() 把该字符串 转换成 字节数组。
char[] toCharArray() 把该字符串 转换成 字符数组。
String replace(char old,char new) 在该字符串中,将给定的旧字符,用新字符替换。
String replace(String old,String new) 在该字符串中, 将给定的旧字符串,用新字符串替换。
String trim() 去除字符串两端空格,中间的不会去除,返回一个新字符串
String toLowerCase() 把该字符串转换成 小写字符串。
String toUpperCase() 把该字符串转换成 大写字符串。
int indexOf(String str,int fromIndex) 从指定位置开始,获取给定的字符串,在该字符串中第一次出现的位置。