字符串 String 广泛应用在Java编程中,在Java中字符串属于对象,Java提供了 String 类来创建和操作字符串。
String类的不可变性
- String类是final修饰的,一旦创建,就不可改变。
String temp = "a";
temp = "b";
System.out.print(temp);
output->b
"a"的内容并没有改变,新建了字符串"b", temp的指向了"b"的内存地址。
String如何保证不可变性
- String的私有成员属性value[],且是final修饰的。
- final可以保证value[]数组的指向不变,但是不能保证value[]数组的值不变。
- value[]属性私有化切不提供set方法,可以保证value[]的值不被更改。
- 还是可以通过反射去修改value[]数组的值。也不是绝对的不可变。
String为什么要设计成不可变性
- 运行时常量池需要:
- String s = “abc”;
- 执行上述代码时,JVM首先在运行时常量池中查看是否存在String对象“abc”,如果已存在该对象,则不用创建新的String对象“abc”,而是将引用s直接指向运行时常量池中已存在的String对象“abc”;如果不存在该对象,则先在运行时常量池中创建一个新的String对象“abc”,然后将引用s指向运行时常量池中创建的新String对象。
- 执行上述代码时,在运行时常量池中只会创建一个String对象”abc”,这样就节省了内存空间
- 同步
- 因为String对象是不可变的,所以是多线程安全的,同一个String实例可以被多个线程共享。这样就不用因为线程安全问题而使用同步。
- 允许String对象缓存hashcode
- 查看上文JDK1.8中String类源码,可以发现其中有一个字段hash,String类的不可变性保证了hashcode的唯一性,所以可以用hash字段对String对象的hashcode进行缓存,就不需要每次重新计算hashcode。所以Java中String对象经常被用来作为HashMap等容器的键。
- 出于安全性考虑
- 字符串常常作为网络连接、数据库连接等參数。不可变就能够保证连接的安全性。
String字符串拼接方式
- 直接用+号:使用StringBuilder的append拼接,每次拼接,都会构造出来一个StringBuilder对象。浪费内存。
- 使用String的concat()方法:concat其实就是申请一个char类型的buf数组,将需要拼接的字符串都放在这个数组里,最后再转换成String对象。
- 使用StringBuilder的append:实现append的方法是调用父类AbstractStringBuilder的append方法。不是线程安全的。
- 使用StringBuffer的append:实现append的方法是调用父类AbstractStringBuilder的append方法。StringBuffer是的append方法加了sychronized关键字,因此是线程安全的。
- 结论:
- 无论如何直接用“+”号连接字符串都是最慢的
- 在拼接少数字符串(不超过4个)的时候,concat效率是最高的
- 多个字符串拼接的时候,StringBuilder/StringBuffer的效率是碾压的
- 在不需要考虑线程安全问题的时候,使用StringBuilder的效率比StringBuffer更高
switch对String的支持
- jdk1.7之前,switch只支持byte,short,int,char
- jdk1.7增加了switch对String的支持,是通过String的hashcode值做比较的。如果hashcode值一样,就在通过equals方法来比较。
理解字符串常量池和intern方法
- https://www.cnblogs.com/justcooooode/p/7603381.html
- https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html
容易采坑的点
- replaceFirst():用于将目标字符串中匹配某正则表达式的第一个子字符串替换成新的字符串。
- replaceAll():用于将目标字符串中匹配某正则表达式的所有子字符串替换成新的字符串
- replace():会将字符串中所有 oldChar 替换成 newChar。
- +号的重载: tring的+操作根本不是重载,他只是JVM做的有个简化操作,实际上还是调用了StringBuilder进行相加。
- String.valueOf():它可以将JAVA基本类型(int,double,boolean等)和对象(Object)转换成String类型。如果参数是NULL,会返回”null”字符串。
- Integer.toString():返回10进制的字符串。可以指定返回多少进制的字符串。