Java中String、StringBuffer及StringBuilder的区别

来源:互联网 发布:win7网络登录密码 编辑:程序博客网 时间:2024/05/19 22:24

一、String介绍

先看下官方文档对String的介绍:

The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:     String str = "abc";is equivalent to:     char data[] = {'a', 'b', 'c'};     String str = new String(data);Here are some more examples of how strings can be used:     System.out.println("abc");     String cde = "cde";     System.out.println("abc" + cde);     String c = "abc".substring(2,3);     String d = cde.substring(1, 2);The class String includes methods for examining individual characters of the sequence, for comparing strings, for searching strings, for extracting substrings, and for creating a copy of a string with all characters translated to uppercase or to lowercase. Case mapping is based on the Unicode Standard version specified by the Character class.The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java. For additional information on string concatenation and conversion, see Gosling, Joy, and Steele, The Java Language Specification.Unless otherwise noted, passing a null argument to a constructor or method in this class will cause a NullPointerException to be thrown.A String represents a string in the UTF-16 format in which supplementary characters are represented by surrogate pairs (see the section Unicode Character Representations in the Character class for more information). Index values refer to char code units, so a supplementary character uses two positions in a String.The String class provides methods for dealing with Unicode code points (i.e., characters), in addition to those for dealing with Unicode code units (i.e., char values).

从介绍中可看到String是字符串常量,字符串长度不变,它是Immutable的。从String类的实现也可以看到它加了final标识符。

使用String主要注意的点:
1. String类初始化后是不可变的(immutable);

String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”;就有四个字符串常量,最终由于String的不可变导致通过“+”产生了很多不必要的临时变量,这种情况下使用StringBuffer或StringBuilder更好。
2. 使用String不一定创建对象;

在执行到双引号包含字符串的语句时,如String a = “123”,JVM会先到常量池里查找,如果有的话返回常量池里的这个实例的引用,否则的话创建一个新实例并置入常量池里。只有通过new()方法才能保证每次都创建一个新的对象。
3. 使用new String,一定创建对象;

在执行String a = new String(“123”)的时候,首先走常量池的路线取到一个实例的引用(若没有,则创建一个”abc”对象),然后再通过new关键字创建一个新的String实例,实际上有可能创建了两个String对象。
4. String.intern()方法;

tring的 intern()方法就是扩充常量池的 一个方法;当一个String实例str调用intern()方法时,Java 查找常量池中 是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用。比如:

String s0 = "kvill"; String s1 = new String("kvill"); String s2 = new String("kvill"); System.out.println( s0 == s1 ); //falseSystem.out.println( "**********" ); s1.intern(); //虽然执行了s1.intern(),但它的返回值没有赋给s1s2 = s2.intern(); //把常量池中"kvill"的引用赋给s2 System.out.println( s0 == s1); //flaseSystem.out.println( s0 == s1.intern() ); //true//说明s1.intern()返回的是常量池中"kvill"的引用System.out.println( s0 == s2 ); //true

二、StringBuffer介绍

官方对StringBuffer的定义:

A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. At any point in time it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls.String buffers are safe for use by multiple threads. The methods are synchronized where necessary so that all the operations on any particular instance behave as if they occur in some serial order that is consistent with the order of the method calls made by each of the individual threads involved.The principal operations on a StringBuffer are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string buffer. The append method always adds these characters at the end of the buffer; the insert method adds the characters at a specified point.For example, if z refers to a string buffer object whose current contents are "start", then the method call z.append("le") would cause the string buffer to contain "startle", whereas z.insert(4, "le") would alter the string buffer to contain "starlet".In general, if sb refers to an instance of a StringBuffer, then sb.append(x) has the same effect as sb.insert(sb.length(), x).Whenever an operation occurs involving a source sequence (such as appending or inserting from a source sequence) this class synchronizes only on the string buffer performing the operation, not on the source.Every string buffer has a capacity. As long as the length of the character sequence contained in the string buffer does not exceed the capacity, it is not necessary to allocate a new internal buffer array. If the internal buffer overflows, it is automatically made larger. As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.

从定义也可知:StringBuffer是线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append(“le”) 会使字符串缓冲区包含“startle”,而 z.insert(4, “le”) 将更改字符串缓冲区,使之包含“starlet”。

使用StringBuffer类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。

三、StringBuilder介绍

Java中对StringBuider的定义:

A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.The principal operations on a StringBuilder are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. The append method always adds these characters at the end of the builder; the insert method adds the characters at a specified point.For example, if z refers to a string builder object whose current contents are "start", then the method call z.append("le") would cause the string builder to contain "startle", whereas z.insert(4, "le") would alter the string builder to contain "starlet".In general, if sb refers to an instance of a StringBuilder, then sb.append(x) has the same effect as sb.insert(sb.length(), x). Every string builder has a capacity. As long as the length of the character sequence contained in the string builder does not exceed the capacity, it is not necessary to allocate a new internal buffer. If the internal buffer overflows, it is automatically made larger.Instances of StringBuilder are not safe for use by multiple threads. If such synchronization is required then it is recommended that StringBuffer be used.

介绍上也说了,StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。速度相较于StringBuffer要更快。

四、String、StringBuffer及StringBuilder使用

  • 如果要操作少量的数据,用String;
  • 单线程操作大量数据,用StringBuilder;
  • 多线程操作大量数据,用StringBuffer;
  • 不要使用String类的”+”来进行频繁的拼接,因为性能很差,应该使用StringBuffer或StringBuilder类;
  • 为了获得更好的性能,在构造StringBuffer或StringBuilder时应尽可能指定它们的容量,默认构造的容量为16个字符;
  • StringBuilder一般使用在方法内部来完成类似”+”功能,因为是线程不安全的,所以用完以后可以丢弃。StringBuffer主要用在全局变量中;

StringBuffer和StringBuilder都是继承自AbstractStringBuilder的,AbstractStringBuilder原理:AbstractStringBuilder中采用一个char数组来保存需要append的字符串,char数组有一个初始大小,当append的字符串长度超过当前char数组容量时,则对char数组进行动态扩展,也即重新申请一段更大的内存空间,然后将当前char数组拷贝到新的位置,因为重新分配内存并拷贝的开销比较大,所以每次重新申请内存空间都是采用申请大于当前需要的内存空间的方式。

从JDK 1.5开始,带有字符串变量的连接操作(+),JVM内部采用的是StringBuilder来实现的,而之前这个操作是采用StringBuffer实现的。

2 0
原创粉丝点击