String、StringBuilder、StringBuffer的区别
面试官可以考察的内容
如果继续深入,面试官可以从各种不同的角度考察,比如可以:
- 通过 String 和相关类,考察基本的线程安全设计与实现,各种基础编程实践。
- 考察 JVM 对象缓存机制的理解以及如何良好地使用。
- 考察 JVM 优化 Java 代码的一些技巧。
- String 相关类的演进,比如 Java 9 中实现的巨大变化。…
String
String、StringBuilder、StringBuffer的区别
String为什么不可变
String类满足了不可变类的定义。
- 用final关键修饰,所以String类不会被继承,避免了子类破坏String类的不可变性
- 保存字符串的数组用final修饰并且是私有的,而且String类没有提供修改这个字符串的方法,所以外部类也无法访问和修改。
不可变类只是其实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例的时候就提供,并且在对象的整个生命周期内固定不变。为了使类不可变,要遵循下面五条规则:
1. 不要提供任何会修改对象状态的方法。
2. 保证类不会被扩展。一般的做法是让这个类成为 final的,防止子类化,破坏该类的不可变行为。
3. 使所有的域都是 final 的。
4. 使所有的域都成为私有的。防止客户端获得访问被域引用的可变对象的权限,并防止客户端直接修改这些对象。
5. 确保对于任何可变性组件的互斥访问。 如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象的引用。
Java 9 为何要将 String的底层实现由char[]改成了byte[] ?
新版的 String 其实支持两个编码方案:Latin-1 和 UTF-16。如果字符串中包含的汉字没有超过 Latin-1 可表示范围内的字符,那就会使用 Latin-1 作为编码方案。Latin-1 编码方案下,
byte
占一个字节(8 位),char
占用 2 个字节(16),byte
相较char
节省一半的内存空间。JDK 官方就说了绝大部分字符串对象只包含 Latin-1 可表示的字符。
如果字符串中包含的汉字超过 Latin-1 可表示范围内的字符,
byte
和char
所占用的空间是一样的。这是官方的介绍:openjdk.java.net/jeps/254 。
字符串拼接,用+ 还是StringBuilder
Java 语言本身并不支持运算符重载(?),“+”和“+=”是专门为 String 类重载过的运算符,也是 Java 中仅有的两个重载过的运算符。
String str1 = "he";
String str2 = "llo";
String str3 = "world";
String str4 = str1 + str2 + str3;
上面的代码对应的字节码如下:
可以看出,字符串对象通过“+”的字符串拼接方式,实际上是通过 StringBuilder
调用 append()
方法实现的,拼接完成之后调用 toString()
得到一个 String
对象 。
不过,在for循环内使用“+”进行字符串的拼接的话,存在比较明显的缺陷:StringBuilder
对象是在循环内部被创建的,这意味着每循环一次就会创建一个 StringBuilder
对象。编译器不会创建单个 StringBuilder
以复用,会导致创建过多的 StringBuilder
对象。
不过,使用 “+” 进行字符串拼接会产生大量的临时对象的问题在 JDK9 中得到了解决。在 JDK9 当中,字符串相加 “+” 改为了用动态方法
makeConcatWithConstants()
来实现,而不是大量的StringBuilder
了。这个改进是 JDK9 的 JEP 280open in new window
字符串常量池和intern方法
String 类型的变量和常量做“+”运算时发生了什么。
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing"; //常量池中的对象
String str4 = str1 + str2; //在堆上创建的新的对象
String str5 = "string"; //常量池中的对象
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false
对于编译期可以确定值的字符串,也就是常量字符串 ,jvm 会将其存入字符串常量池。并且,字符串常量拼接得到的字符串常量在编译阶段就已经被存放字符串常量池,这个得益于编译器的优化。
参考文章
转载自:https://juejin.cn/post/7332723155718225930