java中String、StringBuffer和StringBuilder区别

原创 2016年05月31日 15:41:04

       Java语中String、StringBuffer、StringBuilder这3个类可以用于对字符串进行操作,下面就来具体讨论一下3者的区别。

       java.lang.String这个类表示一个不可变的字符串类,一旦String对象被创建它的值将不会被改变。而java.lang.StringBuffer和java.lang.StringBuilder都是可变的字符串类,当对象被创建之后仍然可以修改其值。因此,如果使用String来保存一个经常修改的字符串对象,在字符串被修改的过程中使用String要比使用StringBuffer与StringBuilder产生许多额外的附加操作,同时也会产生许多附加的无用的对象,这些无用的对象会被系统垃圾回收器进行回收从而影响程序的性能。

      String与StringBuffer、StringBuilder另外一个区别是在创建对象时String对象可以通过构造函数(String s=

new String("Hello"))来创建,也可以通过赋值(String s="Hello")的方式来创建。而

StringBuffer和StringBuilder只能通过构造函数的方式来创建

       而StringBuffer与StringBuiler的区别主要在于StringBuffer是线程安全的,StringBuilder是线程不安全的,通过观察StringBuffer与StringBuilder对应的append方法源码可以发现有如下区别:

StringBuilder java.lang.StringBuilder.append(Object obj)源码:

    /**
     * Appends the string representation of the specified {@code Object}.
     * The {@code Object} value is converted to a string according to the rule
     * defined by {@link String#valueOf(Object)}.
     *
     * @param obj
     *            the {@code Object} to append.
     * @return this builder.
     * @see String#valueOf(Object)
     */
    public StringBuilder append(Object obj) {
        if (obj == null) {
            appendNull();
        } else {
            append0(obj.toString());
        }
        return this;
    }

StringBuffer java.lang.StringBuffer.append(Object obj)源码:

    /**
     * Adds the string representation of the specified object to the end of this
     * StringBuffer.
     * <p>
     * If the specified object is {@code null} the string {@code "null"} is
     * appended, otherwise the objects {@code toString} is used to get its
     * string representation.
     *
     * @param obj
     *            the object to append (may be null).
     * @return this StringBuffer.
     * @see String#valueOf(Object)
     */
    public synchronized StringBuffer append(Object obj) {
        if (obj == null) {
            appendNull();
        } else {
            append0(obj.toString());
        }
        return this;
    }
       通过以上源码可以发现,StringBuffer一些方法被synchronized同步关键字修饰,而StringBuidler一些方法却没有被关键字synchronized修饰,因此StringBuffer是线程安全的,而StringBuidler是线程不安全的,这也导致了StringBuffer要比StringBuilder效率低

       因此从效率的角度来看,StringBuilder效率最高、StringBuffer效率次之,String效率最低。鉴于这种情况,一般情况下,如果操作的数据量比较小应优先考虑String类;如果是在单线程的程序中操作大量数据从效率的角度出发应该优先考虑StringBuilder;如果是在多线程的程序中操作大量数据从线程安全的角度出发应该优先考虑StringBuffer。

       为了更好地体现String、StringBuffer、StringBuilder三者之间的效率差异,下面给出一个对String、StringBuffer、StringBuilder效率测试的例程。

public class StringBufferAndStringBuilderTest {

	public static void testString()
	{
		String s="Hello";
		String addString="World";
		long startTime=System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			s+=addString;
		}
		long endTime=System.currentTimeMillis();
		long runTime=endTime-startTime;
		System.out.println("testString,运行时间:"+runTime);
	}
	public static void testStringBuffer()
	{
		StringBuffer s=new StringBuffer("Hello");
		String addString="World";
		long startTime=System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			s.append(addString);
		}
		long endTime=System.currentTimeMillis();
		long runTime=endTime-startTime;
		System.out.println("testStringBuffer,运行时间:"+runTime);
	}
	public static void testStringBuilder()
	{
		StringBuilder s=new StringBuilder("Hello");
		String addString="World";
		long startTime=System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			s.append(addString);
		}
		long endTime=System.currentTimeMillis();
		long runTime=endTime-startTime;
		System.out.println("testStringBuilder,运行时间:"+runTime);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		testString();
		testStringBuffer();
		testStringBuilder();
	}

}
       运行结果如下:

测试例程源码(github)

       讨论完String、StringBuffer、StringBuilder三者之间的效率问题之后有一个疑问:StringBuffer与StringBuilder中append方法内部到底是如何实现的呢?话不多说,直接看源码。

这里先看java.lang.StringBuilder.append(char c)这个方法,源码如下:

/**
     * Appends the string representation of the specified {@code char} value.
     * The {@code char} value is converted to a string according to the rule
     * defined by {@link String#valueOf(char)}.
     *
     * @param c
     *            the {@code char} value to append.
     * @return this builder.
     * @see String#valueOf(char)
     */
    public StringBuilder append(char c) {
        append0(c);
        return this;
    }
可以看到StringBuilder.append(char c)内部调用了一个名为append0的方法,查看append0源码内部实现如下:

 final void append0(char ch) {
        if (count == value.length) {
            enlargeBuffer(count + 1);
        }
        value[count++] = ch;
    }
        该方法 java.lang.AbstractStringBuilder抽象类中的一个方法,而StringBuilder和StringBuffer均继承实现了该抽象方法,AbstractStringBuilder.append0(char ch)方法首先判断当前用于存放数据的容器数组容量count是否等于容器数组长度value.length,如果容器数组容量count等于容器数组长度value.length则java.lang.AbstractStringBuilder.enlargeBuffer(int min)调用对容器数组扩容。下面查看java.lang.AbstractStringBuilder.enlargeBuffer(int min)内部实现,其源码如下:

private void enlargeBuffer(int min) {
        int newCount = ((value.length >> 1) + value.length) + 2;
        char[] newData = new char[min > newCount ? min : newCount];
        System.arraycopy(value, 0, newData, 0, count);
        value = newData;
        shared = false;
    }

        在 java.lang.AbstractStringBuilder.enlargeBuffer(int min)方法中首先创建了一个大于原数组value长度的新数组newData,然后调用java.lang.System.arraycopy将旧数组value中每个元素复制拷贝到新数组newData中,最后再让value数组指向newData。即StringBuiler.append方法内部实现过程如下:首先创建了一个比value数组更大的新数组,然后调用数组元素复制拷贝方法java.lang.System.arraycopy将value中的每一个元素复制拷贝到新数组中,最后让value指向这个新数组。

       StringBuffer同样继承自java.lang.AbstractStringBuilder抽象类,StringBuffer.append方法内部实现过程与StringBuilder.append相同,具体细节可以查看相关源码在此就不再讨论。




 


版权声明:本文为博主原创文章,未经博主允许不得转载。

Java基础之String、StringBuffer与StringBuilder的区别及应用场景

1 String、StringBuffer与StringBuilder (1)String 字符串常量; /** Strings are constant; their values cann...
  • chenliguan
  • chenliguan
  • 2016年07月14日 18:35
  • 6253

Java中String、StringBuffer、StringBuilder简述及区别

容我喝杯82年的Java压压惊~~~如有欢迎指正。 1.String:由多个字符组成的一串数据,相当与...
  • MAGIC_JSS
  • MAGIC_JSS
  • 2016年05月10日 23:35
  • 1366

java面试题String,StringBuilder,StringBuffer

String StringBuffer StringBuilder面试题
  • dfdsggdgg
  • dfdsggdgg
  • 2016年05月09日 22:39
  • 2749

Java中String、StringBuilder和StringBuffer的简单区别

String、StringBuilder和StringBuffer的简单区别如下: String:不可变的对象,对String对象进行改变的时候等同于生成了一个新的String对象,然后将引用指向...
  • ClementAD
  • ClementAD
  • 2015年01月17日 14:40
  • 1117

JAVA之String,StringBuffer与StringBuilder三者之间的区别

JAVA之String,StringBuffer与StringBuilder三者之间的区别
  • mmd0308
  • mmd0308
  • 2017年06月16日 16:37
  • 176

java中string stringbuffer和stringBuilder区别

一直想做这3个之间的区别,当我们在开发过程中一般好少去考虑这些 1.在执行效率方面比较:stringbuilder > stringbuffer 2.stringbuffer 与 stringBuil...
  • u014209975
  • u014209975
  • 2016年09月20日 12:07
  • 359

Java中String,StringBuffer,StringBuilder区别与联系

Java中String,StringBuffer,StringBuilder区别与联系
  • u012965373
  • u012965373
  • 2017年12月13日 14:55
  • 106

java中的StringBuilder类的使用, String、StringBuilder、StringBuffer的区别

一、String 和 StringBuilder、StringBuffer的区别一:string是不可变序列,StringBuilder和StringBuffer是可变序列。 1、而StringBui...
  • Iloveyougirls
  • Iloveyougirls
  • 2016年09月17日 11:16
  • 308

面试题之:String,StringBuffer与StringBuilder的区别?

String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全)  简要的说, String 类型和 StringBuffer 类...
  • u014381710
  • u014381710
  • 2015年08月24日 23:23
  • 429

String,StringBuffer,StringBuilder 三者之间的区别是什么?

1.String 字符串产量 2.StringBuffer 字符串变量(线程安全) 3.StringBuilder 字符串变量 (非线程安全) 1.String类型,是java内的对象,...
  • qq_30278639
  • qq_30278639
  • 2016年05月10日 14:09
  • 854
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java中String、StringBuffer和StringBuilder区别
举报原因:
原因补充:

(最多只允许输入30个字)