当前位置: 代码迷 >> 综合 >> String、StringBuilder、StringBuffer之间的区别
  详细解决方案

String、StringBuilder、StringBuffer之间的区别

热度:16   发布时间:2023-11-17 03:08:48.0

String中的++符号操作的原理

/*** @author lizhangyu* @date 2020/6/13 1:30*/
public class StringOperator {
    public static void main(String[] args) {
    StringBuffer sbf = new StringBuffer();String a = "a";String b = "b";String c = "23";String d = "2";String e = d + "3";String ab = a+b;StringBuilder sb = new StringBuilder();sb.append(1);System.out.println(c);System.out.println(e);System.out.println(c == e);}
}
  • 输出的结果为:
23
23
false
  • 字节码如下:
Compiled from "StringOperator.java"
public class test1.StringOperator {
    public test1.StringOperator();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: new           #2                  // class java/lang/StringBuffer3: dup4: invokespecial #3                  // Method java/lang/StringBuffer."<init>":()V7: astore_18: ldc           #4                  // String a10: astore_211: ldc           #5                  // String b13: astore_314: ldc           #6                  // String 2316: astore        418: ldc           #7                  // String 220: astore        522: new           #8                  // class java/lang/StringBuilder25: dup26: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V29: aload         531: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;34: ldc           #11                 // String 336: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;39: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;42: astore        644: new           #8                  // class java/lang/StringBuilder47: dup48: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V51: aload_252: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;55: aload_356: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;59: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;62: astore        764: new           #8                  // class java/lang/StringBuilder67: dup68: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V71: astore        873: aload         875: iconst_176: invokevirtual #13                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;79: pop80: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;83: aload         485: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V88: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;91: aload         693: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V96: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;99: aload         4101: aload         6103: if_acmpne     110106: iconst_1107: goto          111110: iconst_0111: invokevirtual #16                 // Method java/io/PrintStream.println:(Z)V114: return
}
  • 可以看到String++符号操作底层用的是StringBuilder类中的append方法,最后再通过toString()方法进行实现的。

StringBuilder中的append()方法

  • 可以看到方法中调用的是super中的append方法
  @Overridepublic StringBuilder append(int i) {
    super.append(i);return this;}
    /*** Appends the string representation of the {@code int}* argument to this sequence.* <p>* The overall effect is exactly as if the argument were converted* to a string by the method {@link String#valueOf(int)},* and the characters of that string were then* {@link #append(String) appended} to this character sequence.** @param i an {@code int}.* @return a reference to this object.*/public AbstractStringBuilder append(int i) {
    if (i == Integer.MIN_VALUE) {
    append("-2147483648");return this;}int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1: Integer.stringSize(i);int spaceNeeded = count + appendedLength;ensureCapacityInternal(spaceNeeded);Integer.getChars(i, spaceNeeded, value);count = spaceNeeded;return this;}
  • 扩容机制:
    /*** For positive values of {@code minimumCapacity}, this method* behaves like {@code ensureCapacity}, however it is never* synchronized.* If {@code minimumCapacity} is non positive due to numeric* overflow, this method throws {@code OutOfMemoryError}.*/private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious codeif (minimumCapacity - value.length > 0) {
    value = Arrays.copyOf(value,newCapacity(minimumCapacity));}}
  • 复制方法如下:
    /*** Copies the specified array, truncating or padding with null characters (if necessary)* so the copy has the specified length. For all indices that are valid* in both the original array and the copy, the two arrays will contain* identical values. For any indices that are valid in the copy but not* the original, the copy will contain <tt>'\\u000'</tt>. Such indices* will exist if and only if the specified length is greater than that of* the original array.** @param original the array to be copied* @param newLength the length of the copy to be returned* @return a copy of the original array, truncated or padded with null characters* to obtain the specified length* @throws NegativeArraySizeException if <tt>newLength</tt> is negative* @throws NullPointerException if <tt>original</tt> is null* @since 1.6*/public static char[] copyOf(char[] original, int newLength) {
    char[] copy = new char[newLength];System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}

可以看到调用的是 System方法,方法如下:

public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

调用的是native的本地方法

  • getChars()方法如下:
 /*** Places characters representing the integer i into the* character array buf. The characters are placed into* the buffer backwards starting with the least significant* digit at the specified index (exclusive), and working* backwards from there.** Will fail if i == Integer.MIN_VALUE*/static void getChars(int i, int index, char[] buf) {
    int q, r;int charPos = index;char sign = 0;if (i < 0) {
    sign = '-';i = -i;}// Generate two digits per iterationwhile (i >= 65536) {
    q = i / 100;// really: r = i - (q * 100);r = i - ((q << 6) + (q << 5) + (q << 2));i = q;buf [--charPos] = DigitOnes[r];buf [--charPos] = DigitTens[r];}// Fall thru to fast mode for smaller numbers// assert(i <= 65536, i);for (;;) {
    q = (i * 52429) >>> (16+3);r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...buf [--charPos] = digits [r];i = q;if (i == 0) break;}if (sign != 0) {
    buf [--charPos] = sign;}}

StringBuffer和StringBuilder之间的区别

StringBuffer是线程安全的,因为StringBuffer方法加锁了,而StringBuilder方法没有加锁
StringBuffer对应的方法如下:

    @Overridepublic synchronized int length() {
    return count;}@Overridepublic synchronized int capacity() {
    return value.length;}@Overridepublic synchronized void ensureCapacity(int minimumCapacity) {
    super.ensureCapacity(minimumCapacity);}/*** @since 1.5*/@Overridepublic synchronized void trimToSize() {
    super.trimToSize();}/*** @throws IndexOutOfBoundsException {@inheritDoc}* @see #length()*/@Overridepublic synchronized void setLength(int newLength) {
    toStringCache = null;super.setLength(newLength);}/*** @throws IndexOutOfBoundsException {@inheritDoc}* @see #length()*/@Overridepublic synchronized char charAt(int index) {
    if ((index < 0) || (index >= count))throw new StringIndexOutOfBoundsException(index);return value[index];}

StringBuilder对应的方法如下:

        @Overridepublic int indexOf(String str) {
    return super.indexOf(str);}@Overridepublic int indexOf(String str, int fromIndex) {
    return super.indexOf(str, fromIndex);}@Overridepublic int lastIndexOf(String str) {
    return super.lastIndexOf(str);}@Overridepublic int lastIndexOf(String str, int fromIndex) {
    return super.lastIndexOf(str, fromIndex);}@Overridepublic StringBuilder reverse() {
    super.reverse();return this;}
  相关解决方案