java面试:String与StringBuffer、StringBuilder的区别

劳请各位大侠指教:

  • String 是内容不可变的字符串,它的底层用的是final修饰的不可变 字符数组,而 其他2个是可变的,底层用的可变数组
  • 在拼接字符串的时候String每次都生成一个新的对象,StringBuffer在原对象上进行拼接并且是线程安全的,StringBuilder在原对象上进行拼接但是线程不安全。

1、看下源码:

String源码:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
    .....
}

在String 内部 其实是用的 final修饰的 字符数组 ,而 final修饰的变量有如下特性 :

  • 必须赋值,不赋值则编译报错。
    public class StringTest {
    	
        private final String str; // 在类里面没有赋值 则这个地方报错
    
    }
  • 赋值之后就不可变,就是说除了第一次赋值 ,以后的任何赋值方法都会报错。
    public class StringTest {
    	
        private final String str = "123"; 
    
    
    	@Test
    	public void test1(){
    		this.str = "234";  // 这里会报错
    	}
    }
  • 要么在定义的时候赋值,要么在构造函数中赋值 若多个构造函数则每个构造函数都要赋值。
public class StringTest {
	
    private final String str; 

    
    public StringTest(){
    	this.str = "";
    }
    
    public StringTest(String str2){
    	this.str = str2;
    }
}

由此可见 Sting在每次发生变更的时候都是返回一个新的String对象。

2、那么为什么说StringBuffer 是线程安全的,而 StringBuilder是线程不安全的呢 ?

首先StringBuffer 和 StringBuilder 都是 都继承了AbstractStringBuilder ,最后值都存在这个value里面,而且他没有用final修饰 。

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

那么在拼接字符串的时候 ,StringBuffer  使用这么用的

    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

由源码可以看到 append方法用synchronized 修饰,所以他是线程安全的。

而StringBuilder  是这么用的

    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

so : 由此可见。

猜你喜欢

转载自blog.csdn.net/qq_24739007/article/details/87873590
今日推荐