谈谈String
1.String、StringBuffer、StringBuilder有什么区别?
- String不可变,StringBuffer和StringBuilder是可变的
- String和StringBuffer是线程安全的,StringBuilder⾮线程安全
- StringBuilder的执⾏效率⾼于StringBuffer
2.String str = new String(“abc”)创建了⼏个对象
1.是2个对象吗?
1.测试代码
package com.andy;
/**
* @author Andy
* @version 0.0.1
* @since 2023-09-22 09:49
*/
public class StringTest {
public static void main(String[] args) {
String abc = new String("abc");
}
}
2.断点查看
3.向下走一步
4.结论:如果”abc“这个字符串常量不存在,则需要去创建两个对象,分别是‘abc’这个字符串常量,以及‘new String’这个实例对象
2.是1个对象吗?
1.测试代码
package com.andy;
/**
* @author Andy
* @version 0.0.1
* @since 2023-09-22 09:49
*/
public class StringTest {
public static void main(String[] args) {
String str = "abc";
String abc = new String("abc");
}
}
2.断点查看
3.向下走一步
4.结论:如果‘abc’这字符串常量存在,则只会创建一个对象,就是String这个对象
3.结论:String str = new String(“abc”)到底创建了⼏个对象
- 如果字符串常量池中已经存在abc,则创建⼀个对象。如果常量池没有abc则是创建两个对象
- abc是⼀个对象,new String 是⼀个对象。所以,答案是2个或者1个
3.String为什么不可变
1.上源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/**
* 用于字符存储.
*
* 该字段受VM信任,如果String实例是常量,则该字段将被常量折叠。
* 在构建后覆盖此字段将导致问题。
* 此外,它被标记为Stable以信任数组的内容。
* JDK中没有其他工具(目前)提供此功能。
* 这里Stable是安全的,因为value永远不会为空。
*/
@Stable
private final byte[] value;
/**
* 用于以值对字节进行编码的编码标识符。本实现支持的值为LATIN1 UTF16
*
* 该字段受VM信任,如果String实例是常量,则该字段将被常量折叠。
* 在构建后覆盖此字段将导致问题。
*/
private final byte coder;
// Cache the hash code for the string
private int hash; // Default to 0
/**
* 初始化新创建的String对象,使其表示与参数相同的字符序列;
* 换句话说,新创建的字符串是参数字符串的副本。
* 除非需要原始的显式副本,否则不需要使用此构造函数,因为string是不可变的.
*
* @param original
* A {@code String}
*/
@HotSpotIntrinsicCandidate
public String(String original) {
this.value = original.value;
this.coder = original.coder;
this.hash = original.hash;
}
}
2.结论:
- String本身没有提供修改byte[]的方法
- 提供的是private进行修饰,所以只有对象本身去访问,外部访问不了
- 用ffinal+不提供方法
4.StringBuffer和StringBuilder是如何做到可变
1.StringBuffer和StringBuilder没有使⽤final关键字,所以可变
2.StringBuffer和StringBuilder拼接新字符串时可能包含⼀次数组扩容
5.为什么StringBuilder的执⾏效率⾼于StringBuffer
1.StringBuffer是线程安全的,StringBuffer类的每个⽅法都使⽤关键字synchornized关键字修饰
2.多线程操作StringBuffer时会涉及到争抢锁,因此StringBuffer的效率会低
StringBuffer类
StringBuilder类
2.多线程操作StringBuffer时会涉及到争抢锁,因此StringBuffer的效率会低
6.为什么是false
1.请看代码
package com.andy;
/**
* @author Andy
* @version 0.0.1
* @since 2023-09-22 09:49
*/
public class StringTest {
public static void main(String[] args) {
StringBuffer stringbuffer = new StringBuffer("abc");
System.out.println(stringbuffer.toString() == stringbuffer.toString());
}
}
运行结果
2.请看StringBuffer中toString()的源码
@Override
@HotSpotIntrinsicCandidate
public synchronized String toString() {
if (toStringCache == null) {
return toStringCache =
isLatin1() ? StringLatin1.newString(value, 0, count)
: StringUTF16.newString(value, 0, count);
}
return new String(toStringCache);
}
3.原因:每次.toString()时都会new String(toStringCache),所以地址改变了。