ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

面试题:Java8中String、StringBuilder、StringBuffer的区别

2022-06-29 23:32:19  阅读:150  来源: 互联网

标签:面试题 String StringBuffer AbstractStringBuilder StringBuilder 字符串 public


前置知识

字符串创建问题

  1. 常量字符串直接赋值 String str = "hello"; 
    • 当使用字符串常量创建一个字符串时,JVM 首先在字符串常量池中寻找具有相同值的字符串,如果找到了它将返回字符串常量池中的字符串对象的引用。否则它会在字符串常量池中创建字符串对象并返回引用
  2. 使用 new运算法创建 String str = new String("hello");
    1. 在字符串常量池中查找是否有 "hello" 对象

      • 有则返回对应的引用实例
      • 没有则创建对应的实例对象

    2. 在堆中 new 一个 String("hello") 对象

    3. 创建 str 引用,并将  String("hello") 对象地址赋值给 str
  3. 使用运算符 +拼接字符串
    • 字符串常量 + 字符串常量
      • String str = "hello"+" world"; 编译器会直接优化成 "hello world"
    • 字符串变量 + 字符串常量 
      • String str = new String("hello") + "world"; 变量加常量会new一个StringBuilder并且调用StringBuilder.appen()方法将他们拼接在一起,通过toString()方法返回字符串

可变性

String

String部分源码如下

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
    
     ............
}

从String源码中可以得知,String类使用了 final修饰类,意为最终类,同时使用了 final来修饰的字符数组来保存字符串的,一旦String对象被赋予初始值后不可改变。所以 String 对象是不可变的

StringBuilder 与 StringBuffer

StringBuilder部分源码如下

public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
    
    public StringBuilder() {
        //调用父类构造方法
        super(16);
    }

    public StringBuilder(int capacity) {
        //调用父类构造方法
        super(capacity);
    }
    
    .........
}

StringBuffer部分源码如下

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
    
    /**
     * A cache of the last value returned by toString. Cleared whenever the StringBuffer is modified.
     */
    private transient char[] toStringCache;

    public StringBuffer() {
        //调用父类构造方法
        super(16);
    }

    public StringBuffer(int capacity) {
        //调用父类构造方法
        super(capacity);
    }
    
    ...........
}

从StringBuilder和StringBuffer源码可以知道,都继承同一个抽象类 AbstractStringBuilder 。而StringBuilder和StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的。AbstractStringBuilder 构造方法中可知,使用了字符数组来保存字符串,但是没有使用 final 来修饰字符数组,所以StringBuilder和StringBuffer是可变的

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    
    /**
     * The value is used for character storage.
     */
    char[] value;

    int count;

    AbstractStringBuilder() {
    }

    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
    
    ............
}

 线程安全性

 String

 由于String对象是不可变的,可以理解为常量,所以String是线程安全的

 StringBuilder和StringBuffer

 由于StringBuilder和StringBuffer都继承了AbstractStringBuilder,在AbstractStringBuilder中定义很多操作字符串的功能函数,同时StringBuilder和StringBuffer基本都对这些功能函数进行的重写。在StringBuffer重写的方法都加上了 synchronized同步锁,所以StringBuffer是线程安全的,而StringBuilder重写的方法中并没有加入 synchronized同步锁标志,所以是线程不安全的。例子 append(String str)方法 

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
    
    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    
    ...........
}
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
    
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    
    .........
}

 性能问题

由于String是不可变的对象,所以在每次对String类型进行改变时,都会生成一个新的String对象,然后将引用指向新的String对象。因此经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响,特别是当内存中无引用的对象多了,对JVM的GC压力很大

使用StringBuffer类时,每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StringBuilder相比使用StringBuffer仅能获得 少许性能提升,但多线程不安全


总结

  1. 操作少量的数据: String

  2. 单线程操作字符串缓冲区下操作大量数据: StringBuilder

  3. 多线程操作字符串缓冲区下操作大量数据: StringBuffer

标签:面试题,String,StringBuffer,AbstractStringBuilder,StringBuilder,字符串,public
来源: https://www.cnblogs.com/52-IT-y/p/16425299.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有