String、StringBuffer和StringBuilder区别

本文讨论了Java中的String、StringBuffer和StringBuilder的区别,包括String的不可变性、对象创建情况、StringBuffer的线程安全性和StringBuilder的高效性。还分析了为何StringBuilder执行效率高以及toString方法的性能影响。
摘要由CSDN通过智能技术生成

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.断点查看
在这里插入图片描述
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”)到底创建了⼏个对象

  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关键字,所以可变
在这里插入图片描述
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),所以地址改变了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值