String、StringBuffer和StringBuilder区别

谈谈String

  • 1.String、StringBuffer、StringBuilder有什么区别?
  • 2.String str = new String("abc")创建了⼏个对象
    • 1.是2个对象吗?
    • 2.是1个对象吗?
    • 3.结论:String str = new String("abc")到底创建了⼏个对象
  • 3.String为什么不可变
  • 4.StringBuffer和StringBuilder是如何做到可变
  • 5.为什么StringBuilder的执⾏效率⾼于StringBuffer
  • 6.为什么是false

1.String、StringBuffer、StringBuilder有什么区别?

  1. String不可变,StringBuffer和StringBuilder是可变的
  2. String和StringBuffer是线程安全的,StringBuilder⾮线程安全
  3. 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.断点查看
String、StringBuffer和StringBuilder区别_第1张图片
3.向下走一步
String、StringBuffer和StringBuilder区别_第2张图片
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.断点查看
String、StringBuffer和StringBuilder区别_第3张图片
3.向下走一步
String、StringBuffer和StringBuilder区别_第4张图片
4.结论:如果‘abc’这字符串常量存在,则只会创建一个对象,就是String这个对象

3.结论:String str = new String(“abc”)到底创建了⼏个对象

  1. 如果字符串常量池中已经存在abc,则创建⼀个对象。如果常量池没有abc则是创建两个对象
  2. 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关键字,所以可变
String、StringBuffer和StringBuilder区别_第5张图片
2.StringBuffer和StringBuilder拼接新字符串时可能包含⼀次数组扩容
String、StringBuffer和StringBuilder区别_第6张图片

5.为什么StringBuilder的执⾏效率⾼于StringBuffer

1.StringBuffer是线程安全的,StringBuffer类的每个⽅法都使⽤关键字synchornized关键字修饰
2.多线程操作StringBuffer时会涉及到争抢锁,因此StringBuffer的效率会低

StringBuffer类
String、StringBuffer和StringBuilder区别_第7张图片
StringBuilder类
String、StringBuffer和StringBuilder区别_第8张图片
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());

    }
}

运行结果
String、StringBuffer和StringBuilder区别_第9张图片
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),所以地址改变了。

你可能感兴趣的:(java)