
本文共 9678 字,大约阅读时间需要 32 分钟。
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); }}
- 输出的结果为:
2323false
- 字节码如下:
Compiled from "StringOperator.java"public class test1.StringOperator { public test1.StringOperator(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: new #2 // class java/lang/StringBuffer 3: dup 4: invokespecial #3 // Method java/lang/StringBuffer." ":()V 7: astore_1 8: ldc #4 // String a 10: astore_2 11: ldc #5 // String b 13: astore_3 14: ldc #6 // String 23 16: astore 4 18: ldc #7 // String 2 20: astore 5 22: new #8 // class java/lang/StringBuilder 25: dup 26: invokespecial #9 // Method java/lang/StringBuilder." ":()V 29: aload 5 31: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 34: ldc #11 // String 3 36: 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 6 44: new #8 // class java/lang/StringBuilder 47: dup 48: invokespecial #9 // Method java/lang/StringBuilder." ":()V 51: aload_2 52: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 55: aload_3 56: 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 7 64: new #8 // class java/lang/StringBuilder 67: dup 68: invokespecial #9 // Method java/lang/StringBuilder." ":()V 71: astore 8 73: aload 8 75: iconst_1 76: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 79: pop 80: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream; 83: aload 4 85: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 88: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream; 91: aload 6 93: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 96: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream; 99: aload 4 101: aload 6 103: if_acmpne 110 106: iconst_1 107: goto 111 110: iconst_0 111: invokevirtual #16 // Method java/io/PrintStream.println:(Z)V 114: return}
- 可以看到String++符号操作底层用的是StringBuilder类中的append方法,最后再通过toString()方法进行实现的。
StringBuilder中的append()方法
- 可以看到方法中调用的是super中的append方法
@Override public StringBuilder append(int i) { super.append(i); return this; }
/** * Appends the string representation of the {@code int} * argument to this sequence. ** 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 code if (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 '\\u000'. 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 newLength is negative * @throws NullPointerException if original 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 iteration while (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对应的方法如下:@Override public synchronized int length() { return count; } @Override public synchronized int capacity() { return value.length; } @Override public synchronized void ensureCapacity(int minimumCapacity) { super.ensureCapacity(minimumCapacity); } /** * @since 1.5 */ @Override public synchronized void trimToSize() { super.trimToSize(); } /** * @throws IndexOutOfBoundsException {@inheritDoc} * @see #length() */ @Override public synchronized void setLength(int newLength) { toStringCache = null; super.setLength(newLength); } /** * @throws IndexOutOfBoundsException {@inheritDoc} * @see #length() */ @Override public synchronized char charAt(int index) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index); return value[index]; }
StringBuilder对应的方法如下:
@Override public int indexOf(String str) { return super.indexOf(str); } @Override public int indexOf(String str, int fromIndex) { return super.indexOf(str, fromIndex); } @Override public int lastIndexOf(String str) { return super.lastIndexOf(str); } @Override public int lastIndexOf(String str, int fromIndex) { return super.lastIndexOf(str, fromIndex); } @Override public StringBuilder reverse() { super.reverse(); return this; }
发表评论
最新留言
关于作者
