【面试】-String,StringBuffer,StringBuilder他们之间的区别

一String源码解析与测试

  • String内容是不可变的字符串,String的底层是使用一个不可变的字符数组(final关键词修饰)
  • String类是final类,意味着String类是不可被继承的类,其成员都是final修饰,其方法默认都是被final所修饰。
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;
    

由下面的源码可知,无论是substring,concat等操作,都不是对原先的字符串进行操作,而是重新生成了另一个对象(new)。那么平时你对字符串进行操作的时候都不会改变原先的对象,每次操作都会产生新的对象,所以每次进行字符串拼接都会产生新对象。如果在循环中使用字符串拼接,其代价很高。

  public String substring(int beginIndex, int endIndex)
{
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }
    
    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }
    
  • 深入解析"hello world"和new String(“hello world”)区别

str1和str3在编译期间都会在jvm方法区的运行时常量池中产生字面常量和符号引用(不懂jvm内存结构的可以在我公众号找查找一遍文章叫jvm-运行时数据区的介绍。),运行期间执行str1时"hello world"这个字面常量会被保存在常量池中,执行str3的时候会去常量中查询该字面常量,如果已经存在,则直接引用已存在的字面常量;否则会在常量池中开辟一个空间来存储,并将引用指向该字面常量;所以str1=str3;

str2和str4是通过new产生的对象,new对象是存在堆中,堆中是不管对象内容是否一样,都会开辟一个新空间去存储。所以str2!=str4;

str1和str2有什么不同呢?str1只会在常量池创建一个字面常量;在执行str2的时候除了在堆中new一个对象外,还会在常量池中创建字面常量,平时创建字符串常量时不建议使用str2的方式,这会造成内存的额外开销。

   @Test
    public void stringTest(){
        String str1 = "hello world";
        String str2 = new String("hello world");
        String str3 = "hello world";
        String str4 = new String("hello world
        ");

        System.out.println(str1==str2);//false
        System.out.println(str1==str3);//true
        System.out.println(str2==str4);//false
    }
    

二Stringbuilder和Stringbuffer

Stringbuilder和StringBuffer都是继承AbstractStringBuilder;StringBuffer多了个synchronized关键字,是线程安全;Stringbuilder线程不安全

@Override
public StringBuilder append(String str) {
    super.append(str);
    return this;
}
   @Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

三String和StringBuilder

StringBuilder底层是对字符串数组进行操作,在执行期间不会产生新的对象,而前面提到String操作时会产生新对象。

大家有兴趣也可以使用javap命令反编译看看字节码文件。

四String,StringBuilder,StringBuffer何时使用

1不在循环中的字符串,并且字符串拼接少使用String

2在循环中的字符串或者字符串拼接较多使用StringBuilder

3单线程使用StringBuilder,多线程使用StringBuffer。

五作者公众号

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值