Re: [PATCH] AbstractStringBuilder.append()
I think adding a dedicated method would help clarify and encourage performant code. For example, I sped up the snippet below after seeing that StringBuilder.append() has a fast path when the arg is another StringBuilder, which isn't clear from the javadoc. public class ScalaSB implements java.lang.CharSequence { final StringBuilder sb; ... public append(ScalaSB other) { - sb.append(other); +sb.append(other.sb); } }
Re: [PATCH] AbstractStringBuilder.append()
> On Jun 29, 2018, at 2:50 PM, Jonathan Gibbons > wrote: > > In that specific snippet, I would expect the compiler (javac) to fold the > constants together. > Yes, and behold the use of indy string concat :-) Classfile /Users/sandoz/Projects/jdk/jdk-test/target/classes/Test.class Last modified Jun 29, 2018; size 873 bytes MD5 checksum b6eb6030a1b0840263ecced5880a52e6 Compiled from "Test.java" public class Test SourceFile: "Test.java" InnerClasses: public static final #37= #36 of #40; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles BootstrapMethods: 0: #24 invokestatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; Method arguments: #25 bazbiz minor version: 0 major version: 54 flags: ACC_PUBLIC, ACC_SUPER Constant pool: ... #22 = Utf8 barfoo ... #25 = String #30// bazbiz { public Test(); ... public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: ldc #2 // String barfoo 2: astore_1 3: aload_1 4: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String; 9: astore_1 10: return Paul. > -- Jon > > On 06/29/2018 01:02 PM, Isaac Levy wrote: >> Would this snippet end up merging two StringBuilders? >> >> String x = "bar" + "foo"; >> x += "baz" + "biz"; >> >> I had trouble reading stringopts.cpp. I was thinking this append might >> be common due to implicit StringBuilder creation. >> >> Isaac >> >> >> On Fri, Jun 29, 2018 at 12:48 PM, Paul Sandoz wrote: >>> Hard to reconstruct the culture memory around this. I suspect such a new >>> method was not considered necessary when StringBuilder was added to Java >>> 1.5 given the CharSequence accepting method, and performance was not >>> considered a concern, and I doubt it's a concern now. >>> >>> (I don’t think there is any circularity that would result from bridge >>> methods if such a method was added.) >>> >>> Paul. >>> On Jun 27, 2018, at 10:22 PM, Martin Buchholz wrote: I'm fairly sure the append(StringBuilder) overloads were left out intentionally. On Wed, Jun 27, 2018 at 8:57 PM, Isaac Levy wrote: > AbstractStringBuilder already has append(). This patch > adds append(). > > The new method improves parity between the two classes. In addition, > combining StringBuilders is presumably common. append() > has a couple insteadof checks, which this new method skips. > > -Isaac > > > > > diff --git a/src/java.base/share/classes/java/lang/ > AbstractStringBuilder.java > b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java > index 2ef3e53256..1fe89bb92a 100644 > --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java > +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java > @@ -543,6 +543,11 @@ abstract class AbstractStringBuilder implements > Appendable, CharSequence { > return this.append((AbstractStringBuilder)sb); > } > > +// Documentation in subclasses because of synchro difference > +public AbstractStringBuilder append(StringBuilder sb) { > +return this.append((AbstractStringBuilder)sb); > +} > + > /** > * @since 1.8 > */ > diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java > b/src/java.base/share/classes/java/lang/StringBuffer.java > index e597a8112e..613ba90c25 100644 > --- a/src/java.base/share/classes/java/lang/StringBuffer.java > +++ b/src/java.base/share/classes/java/lang/StringBuffer.java > @@ -313,6 +313,33 @@ import jdk.internal.HotSpotIntrinsicCandidate; > return this; > } > > +/** > + * Appends the specified {@code StringBuilder} to this sequence. > + * > + * The characters of the {@code StringBuilder} argument are appended, > + * in order, to the contents of this {@code StringBuffer}, increasing > the > + * length of this {@code StringBuffer} by the length of the argument. > + * If {@code sb} is {@code null}, then the four characters > + * {@code "null"} are appended to this {@code StringBuffer}. > + * > + * Let n be the length of the old character sequence, the one > + * contained in the {@code StringBuffer} just prior to execution of > the > + * {@code append} method. Then the character at index k in > + * the new
Re: [PATCH] AbstractStringBuilder.append()
In that specific snippet, I would expect the compiler (javac) to fold the constants together. -- Jon On 06/29/2018 01:02 PM, Isaac Levy wrote: Would this snippet end up merging two StringBuilders? String x = "bar" + "foo"; x += "baz" + "biz"; I had trouble reading stringopts.cpp. I was thinking this append might be common due to implicit StringBuilder creation. Isaac On Fri, Jun 29, 2018 at 12:48 PM, Paul Sandoz wrote: Hard to reconstruct the culture memory around this. I suspect such a new method was not considered necessary when StringBuilder was added to Java 1.5 given the CharSequence accepting method, and performance was not considered a concern, and I doubt it's a concern now. (I don’t think there is any circularity that would result from bridge methods if such a method was added.) Paul. On Jun 27, 2018, at 10:22 PM, Martin Buchholz wrote: I'm fairly sure the append(StringBuilder) overloads were left out intentionally. On Wed, Jun 27, 2018 at 8:57 PM, Isaac Levy wrote: AbstractStringBuilder already has append(). This patch adds append(). The new method improves parity between the two classes. In addition, combining StringBuilders is presumably common. append() has a couple insteadof checks, which this new method skips. -Isaac diff --git a/src/java.base/share/classes/java/lang/ AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index 2ef3e53256..1fe89bb92a 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -543,6 +543,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { return this.append((AbstractStringBuilder)sb); } +// Documentation in subclasses because of synchro difference +public AbstractStringBuilder append(StringBuilder sb) { +return this.append((AbstractStringBuilder)sb); +} + /** * @since 1.8 */ diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java index e597a8112e..613ba90c25 100644 --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -313,6 +313,33 @@ import jdk.internal.HotSpotIntrinsicCandidate; return this; } +/** + * Appends the specified {@code StringBuilder} to this sequence. + * + * The characters of the {@code StringBuilder} argument are appended, + * in order, to the contents of this {@code StringBuffer}, increasing the + * length of this {@code StringBuffer} by the length of the argument. + * If {@code sb} is {@code null}, then the four characters + * {@code "null"} are appended to this {@code StringBuffer}. + * + * Let n be the length of the old character sequence, the one + * contained in the {@code StringBuffer} just prior to execution of the + * {@code append} method. Then the character at index k in + * the new character sequence is equal to the character at index k + * in the old character sequence, if k is less than n; + * otherwise, it is equal to the character at index k-n in the + * argument {@code sb}. + * + * + * @param sb the {@code StringBuilder} to append. + * @return a reference to this object. + */ +public synchronized StringBuffer append(StringBuilder sb) { +toStringCache = null; +super.append(sb); +return this; +} + /** * Appends the specified {@code StringBuffer} to this sequence. * diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java b/src/java.base/share/classes/java/lang/StringBuilder.java index 40da2083c2..5ddd4fb5f9 100644 --- a/src/java.base/share/classes/java/lang/StringBuilder.java +++ b/src/java.base/share/classes/java/lang/StringBuilder.java @@ -199,6 +199,30 @@ public final class StringBuilder return this; } +/** + * Appends the specified {@code StringBuilder} to this sequence. + * + * The characters of the {@code StringBuilder} argument are appended, + * in order, to this sequence, increasing the + * length of this sequence by the length of the argument. + * If {@code sb} is {@code null}, then the four characters + * {@code "null"} are appended to this sequence. + * + * Let n be the length of this character sequence just prior to + * execution of the {@code append} method. Then the character at index + * k in the new character sequence is equal to the character at + * index k in the old character sequence, if k is less than + * n; otherwise, it is equal to the character at index k-n + * in the argument {@code sb}. + * + * @param sb the {@code StringBuilder} to append. + * @return a reference to this object. + */ +public StringBuilder append(StringBuilder sb) { +
Re: [PATCH] AbstractStringBuilder.append()
Would this snippet end up merging two StringBuilders? String x = "bar" + "foo"; x += "baz" + "biz"; I had trouble reading stringopts.cpp. I was thinking this append might be common due to implicit StringBuilder creation. Isaac On Fri, Jun 29, 2018 at 12:48 PM, Paul Sandoz wrote: > Hard to reconstruct the culture memory around this. I suspect such a new > method was not considered necessary when StringBuilder was added to Java 1.5 > given the CharSequence accepting method, and performance was not considered a > concern, and I doubt it's a concern now. > > (I don’t think there is any circularity that would result from bridge methods > if such a method was added.) > > Paul. > >> On Jun 27, 2018, at 10:22 PM, Martin Buchholz wrote: >> >> I'm fairly sure the append(StringBuilder) overloads were left out >> intentionally. >> >> On Wed, Jun 27, 2018 at 8:57 PM, Isaac Levy wrote: >> >>> AbstractStringBuilder already has append(). This patch >>> adds append(). >>> >>> The new method improves parity between the two classes. In addition, >>> combining StringBuilders is presumably common. append() >>> has a couple insteadof checks, which this new method skips. >>> >>> -Isaac >>> >>> >>> >>> >>> diff --git a/src/java.base/share/classes/java/lang/ >>> AbstractStringBuilder.java >>> b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >>> index 2ef3e53256..1fe89bb92a 100644 >>> --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >>> +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >>> @@ -543,6 +543,11 @@ abstract class AbstractStringBuilder implements >>> Appendable, CharSequence { >>> return this.append((AbstractStringBuilder)sb); >>> } >>> >>> +// Documentation in subclasses because of synchro difference >>> +public AbstractStringBuilder append(StringBuilder sb) { >>> +return this.append((AbstractStringBuilder)sb); >>> +} >>> + >>> /** >>> * @since 1.8 >>> */ >>> diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java >>> b/src/java.base/share/classes/java/lang/StringBuffer.java >>> index e597a8112e..613ba90c25 100644 >>> --- a/src/java.base/share/classes/java/lang/StringBuffer.java >>> +++ b/src/java.base/share/classes/java/lang/StringBuffer.java >>> @@ -313,6 +313,33 @@ import jdk.internal.HotSpotIntrinsicCandidate; >>> return this; >>> } >>> >>> +/** >>> + * Appends the specified {@code StringBuilder} to this sequence. >>> + * >>> + * The characters of the {@code StringBuilder} argument are appended, >>> + * in order, to the contents of this {@code StringBuffer}, increasing >>> the >>> + * length of this {@code StringBuffer} by the length of the argument. >>> + * If {@code sb} is {@code null}, then the four characters >>> + * {@code "null"} are appended to this {@code StringBuffer}. >>> + * >>> + * Let n be the length of the old character sequence, the one >>> + * contained in the {@code StringBuffer} just prior to execution of >>> the >>> + * {@code append} method. Then the character at index k in >>> + * the new character sequence is equal to the character at index >>> k >>> + * in the old character sequence, if k is less than n; >>> + * otherwise, it is equal to the character at index k-n in the >>> + * argument {@code sb}. >>> + * >>> + * >>> + * @param sb the {@code StringBuilder} to append. >>> + * @return a reference to this object. >>> + */ >>> +public synchronized StringBuffer append(StringBuilder sb) { >>> +toStringCache = null; >>> +super.append(sb); >>> +return this; >>> +} >>> + >>> /** >>> * Appends the specified {@code StringBuffer} to this sequence. >>> * >>> diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java >>> b/src/java.base/share/classes/java/lang/StringBuilder.java >>> index 40da2083c2..5ddd4fb5f9 100644 >>> --- a/src/java.base/share/classes/java/lang/StringBuilder.java >>> +++ b/src/java.base/share/classes/java/lang/StringBuilder.java >>> @@ -199,6 +199,30 @@ public final class StringBuilder >>> return this; >>> } >>> >>> +/** >>> + * Appends the specified {@code StringBuilder} to this sequence. >>> + * >>> + * The characters of the {@code StringBuilder} argument are appended, >>> + * in order, to this sequence, increasing the >>> + * length of this sequence by the length of the argument. >>> + * If {@code sb} is {@code null}, then the four characters >>> + * {@code "null"} are appended to this sequence. >>> + * >>> + * Let n be the length of this character sequence just prior to >>> + * execution of the {@code append} method. Then the character at index >>> + * k in the new character sequence is equal to the character at >>> + * index k in the old character sequence, if k is less >>> than >>> + * n; otherwise, it is equal to the
Re: [PATCH] AbstractStringBuilder.append()
Hard to reconstruct the culture memory around this. I suspect such a new method was not considered necessary when StringBuilder was added to Java 1.5 given the CharSequence accepting method, and performance was not considered a concern, and I doubt it's a concern now. (I don’t think there is any circularity that would result from bridge methods if such a method was added.) Paul. > On Jun 27, 2018, at 10:22 PM, Martin Buchholz wrote: > > I'm fairly sure the append(StringBuilder) overloads were left out > intentionally. > > On Wed, Jun 27, 2018 at 8:57 PM, Isaac Levy wrote: > >> AbstractStringBuilder already has append(). This patch >> adds append(). >> >> The new method improves parity between the two classes. In addition, >> combining StringBuilders is presumably common. append() >> has a couple insteadof checks, which this new method skips. >> >> -Isaac >> >> >> >> >> diff --git a/src/java.base/share/classes/java/lang/ >> AbstractStringBuilder.java >> b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >> index 2ef3e53256..1fe89bb92a 100644 >> --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >> +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >> @@ -543,6 +543,11 @@ abstract class AbstractStringBuilder implements >> Appendable, CharSequence { >> return this.append((AbstractStringBuilder)sb); >> } >> >> +// Documentation in subclasses because of synchro difference >> +public AbstractStringBuilder append(StringBuilder sb) { >> +return this.append((AbstractStringBuilder)sb); >> +} >> + >> /** >> * @since 1.8 >> */ >> diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java >> b/src/java.base/share/classes/java/lang/StringBuffer.java >> index e597a8112e..613ba90c25 100644 >> --- a/src/java.base/share/classes/java/lang/StringBuffer.java >> +++ b/src/java.base/share/classes/java/lang/StringBuffer.java >> @@ -313,6 +313,33 @@ import jdk.internal.HotSpotIntrinsicCandidate; >> return this; >> } >> >> +/** >> + * Appends the specified {@code StringBuilder} to this sequence. >> + * >> + * The characters of the {@code StringBuilder} argument are appended, >> + * in order, to the contents of this {@code StringBuffer}, increasing >> the >> + * length of this {@code StringBuffer} by the length of the argument. >> + * If {@code sb} is {@code null}, then the four characters >> + * {@code "null"} are appended to this {@code StringBuffer}. >> + * >> + * Let n be the length of the old character sequence, the one >> + * contained in the {@code StringBuffer} just prior to execution of >> the >> + * {@code append} method. Then the character at index k in >> + * the new character sequence is equal to the character at index >> k >> + * in the old character sequence, if k is less than n; >> + * otherwise, it is equal to the character at index k-n in the >> + * argument {@code sb}. >> + * >> + * >> + * @param sb the {@code StringBuilder} to append. >> + * @return a reference to this object. >> + */ >> +public synchronized StringBuffer append(StringBuilder sb) { >> +toStringCache = null; >> +super.append(sb); >> +return this; >> +} >> + >> /** >> * Appends the specified {@code StringBuffer} to this sequence. >> * >> diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java >> b/src/java.base/share/classes/java/lang/StringBuilder.java >> index 40da2083c2..5ddd4fb5f9 100644 >> --- a/src/java.base/share/classes/java/lang/StringBuilder.java >> +++ b/src/java.base/share/classes/java/lang/StringBuilder.java >> @@ -199,6 +199,30 @@ public final class StringBuilder >> return this; >> } >> >> +/** >> + * Appends the specified {@code StringBuilder} to this sequence. >> + * >> + * The characters of the {@code StringBuilder} argument are appended, >> + * in order, to this sequence, increasing the >> + * length of this sequence by the length of the argument. >> + * If {@code sb} is {@code null}, then the four characters >> + * {@code "null"} are appended to this sequence. >> + * >> + * Let n be the length of this character sequence just prior to >> + * execution of the {@code append} method. Then the character at index >> + * k in the new character sequence is equal to the character at >> + * index k in the old character sequence, if k is less >> than >> + * n; otherwise, it is equal to the character at index >> k-n >> + * in the argument {@code sb}. >> + * >> + * @param sb the {@code StringBuilder} to append. >> + * @return a reference to this object. >> + */ >> +public StringBuilder append(StringBuilder sb) { >> +super.append(sb); >> +return this; >> +} >> + >> @Override >> public StringBuilder append(CharSequence s) { >>
Re: [PATCH] AbstractStringBuilder.append()
On Thu, Jun 28, 2018 at 11:59 AM, Isaac Levy wrote: > And can't remove append(StringBuffer) because of binary compatibility? > That seems right. --- Also, the JIT can optijmize away any instanceof checks after inining when it sees append(stringBuilder). And any optimizations here are far less critical than they would be if they applied to each individual char.
Re: [PATCH] AbstractStringBuilder.append()
And can't remove append(StringBuffer) because of binary compatibility? Isaac On Thu, Jun 28, 2018 at 1:22 AM, Martin Buchholz wrote: > I'm fairly sure the append(StringBuilder) overloads were left out > intentionally. > > On Wed, Jun 27, 2018 at 8:57 PM, Isaac Levy wrote: >> >> AbstractStringBuilder already has append(). This patch >> adds append(). >> >> The new method improves parity between the two classes. In addition, >> combining StringBuilders is presumably common. append() >> has a couple insteadof checks, which this new method skips. >> >> -Isaac >> >> >> >> >> diff --git >> a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >> b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >> index 2ef3e53256..1fe89bb92a 100644 >> --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >> +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java >> @@ -543,6 +543,11 @@ abstract class AbstractStringBuilder implements >> Appendable, CharSequence { >> return this.append((AbstractStringBuilder)sb); >> } >> >> +// Documentation in subclasses because of synchro difference >> +public AbstractStringBuilder append(StringBuilder sb) { >> +return this.append((AbstractStringBuilder)sb); >> +} >> + >> /** >> * @since 1.8 >> */ >> diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java >> b/src/java.base/share/classes/java/lang/StringBuffer.java >> index e597a8112e..613ba90c25 100644 >> --- a/src/java.base/share/classes/java/lang/StringBuffer.java >> +++ b/src/java.base/share/classes/java/lang/StringBuffer.java >> @@ -313,6 +313,33 @@ import jdk.internal.HotSpotIntrinsicCandidate; >> return this; >> } >> >> +/** >> + * Appends the specified {@code StringBuilder} to this sequence. >> + * >> + * The characters of the {@code StringBuilder} argument are appended, >> + * in order, to the contents of this {@code StringBuffer}, increasing >> the >> + * length of this {@code StringBuffer} by the length of the argument. >> + * If {@code sb} is {@code null}, then the four characters >> + * {@code "null"} are appended to this {@code StringBuffer}. >> + * >> + * Let n be the length of the old character sequence, the one >> + * contained in the {@code StringBuffer} just prior to execution of >> the >> + * {@code append} method. Then the character at index k in >> + * the new character sequence is equal to the character at index >> k >> + * in the old character sequence, if k is less than n; >> + * otherwise, it is equal to the character at index k-n in the >> + * argument {@code sb}. >> + * >> + * >> + * @param sb the {@code StringBuilder} to append. >> + * @return a reference to this object. >> + */ >> +public synchronized StringBuffer append(StringBuilder sb) { >> +toStringCache = null; >> +super.append(sb); >> +return this; >> +} >> + >> /** >> * Appends the specified {@code StringBuffer} to this sequence. >> * >> diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java >> b/src/java.base/share/classes/java/lang/StringBuilder.java >> index 40da2083c2..5ddd4fb5f9 100644 >> --- a/src/java.base/share/classes/java/lang/StringBuilder.java >> +++ b/src/java.base/share/classes/java/lang/StringBuilder.java >> @@ -199,6 +199,30 @@ public final class StringBuilder >> return this; >> } >> >> +/** >> + * Appends the specified {@code StringBuilder} to this sequence. >> + * >> + * The characters of the {@code StringBuilder} argument are appended, >> + * in order, to this sequence, increasing the >> + * length of this sequence by the length of the argument. >> + * If {@code sb} is {@code null}, then the four characters >> + * {@code "null"} are appended to this sequence. >> + * >> + * Let n be the length of this character sequence just prior >> to >> + * execution of the {@code append} method. Then the character at >> index >> + * k in the new character sequence is equal to the character >> at >> + * index k in the old character sequence, if k is less >> than >> + * n; otherwise, it is equal to the character at index >> k-n >> + * in the argument {@code sb}. >> + * >> + * @param sb the {@code StringBuilder} to append. >> + * @return a reference to this object. >> + */ >> +public StringBuilder append(StringBuilder sb) { >> +super.append(sb); >> +return this; >> +} >> + >> @Override >> public StringBuilder append(CharSequence s) { >> super.append(s); > >
Re: [PATCH] AbstractStringBuilder.append()
I'm fairly sure the append(StringBuilder) overloads were left out intentionally. On Wed, Jun 27, 2018 at 8:57 PM, Isaac Levy wrote: > AbstractStringBuilder already has append(). This patch > adds append(). > > The new method improves parity between the two classes. In addition, > combining StringBuilders is presumably common. append() > has a couple insteadof checks, which this new method skips. > > -Isaac > > > > > diff --git a/src/java.base/share/classes/java/lang/ > AbstractStringBuilder.java > b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java > index 2ef3e53256..1fe89bb92a 100644 > --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java > +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java > @@ -543,6 +543,11 @@ abstract class AbstractStringBuilder implements > Appendable, CharSequence { > return this.append((AbstractStringBuilder)sb); > } > > +// Documentation in subclasses because of synchro difference > +public AbstractStringBuilder append(StringBuilder sb) { > +return this.append((AbstractStringBuilder)sb); > +} > + > /** > * @since 1.8 > */ > diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java > b/src/java.base/share/classes/java/lang/StringBuffer.java > index e597a8112e..613ba90c25 100644 > --- a/src/java.base/share/classes/java/lang/StringBuffer.java > +++ b/src/java.base/share/classes/java/lang/StringBuffer.java > @@ -313,6 +313,33 @@ import jdk.internal.HotSpotIntrinsicCandidate; > return this; > } > > +/** > + * Appends the specified {@code StringBuilder} to this sequence. > + * > + * The characters of the {@code StringBuilder} argument are appended, > + * in order, to the contents of this {@code StringBuffer}, increasing > the > + * length of this {@code StringBuffer} by the length of the argument. > + * If {@code sb} is {@code null}, then the four characters > + * {@code "null"} are appended to this {@code StringBuffer}. > + * > + * Let n be the length of the old character sequence, the one > + * contained in the {@code StringBuffer} just prior to execution of > the > + * {@code append} method. Then the character at index k in > + * the new character sequence is equal to the character at index > k > + * in the old character sequence, if k is less than n; > + * otherwise, it is equal to the character at index k-n in the > + * argument {@code sb}. > + * > + * > + * @param sb the {@code StringBuilder} to append. > + * @return a reference to this object. > + */ > +public synchronized StringBuffer append(StringBuilder sb) { > +toStringCache = null; > +super.append(sb); > +return this; > +} > + > /** > * Appends the specified {@code StringBuffer} to this sequence. > * > diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java > b/src/java.base/share/classes/java/lang/StringBuilder.java > index 40da2083c2..5ddd4fb5f9 100644 > --- a/src/java.base/share/classes/java/lang/StringBuilder.java > +++ b/src/java.base/share/classes/java/lang/StringBuilder.java > @@ -199,6 +199,30 @@ public final class StringBuilder > return this; > } > > +/** > + * Appends the specified {@code StringBuilder} to this sequence. > + * > + * The characters of the {@code StringBuilder} argument are appended, > + * in order, to this sequence, increasing the > + * length of this sequence by the length of the argument. > + * If {@code sb} is {@code null}, then the four characters > + * {@code "null"} are appended to this sequence. > + * > + * Let n be the length of this character sequence just prior to > + * execution of the {@code append} method. Then the character at index > + * k in the new character sequence is equal to the character at > + * index k in the old character sequence, if k is less > than > + * n; otherwise, it is equal to the character at index > k-n > + * in the argument {@code sb}. > + * > + * @param sb the {@code StringBuilder} to append. > + * @return a reference to this object. > + */ > +public StringBuilder append(StringBuilder sb) { > +super.append(sb); > +return this; > +} > + > @Override > public StringBuilder append(CharSequence s) { > super.append(s); >
[PATCH] AbstractStringBuilder.append()
AbstractStringBuilder already has append(). This patch adds append(). The new method improves parity between the two classes. In addition, combining StringBuilders is presumably common. append() has a couple insteadof checks, which this new method skips. -Isaac diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index 2ef3e53256..1fe89bb92a 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -543,6 +543,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { return this.append((AbstractStringBuilder)sb); } +// Documentation in subclasses because of synchro difference +public AbstractStringBuilder append(StringBuilder sb) { +return this.append((AbstractStringBuilder)sb); +} + /** * @since 1.8 */ diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java index e597a8112e..613ba90c25 100644 --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -313,6 +313,33 @@ import jdk.internal.HotSpotIntrinsicCandidate; return this; } +/** + * Appends the specified {@code StringBuilder} to this sequence. + * + * The characters of the {@code StringBuilder} argument are appended, + * in order, to the contents of this {@code StringBuffer}, increasing the + * length of this {@code StringBuffer} by the length of the argument. + * If {@code sb} is {@code null}, then the four characters + * {@code "null"} are appended to this {@code StringBuffer}. + * + * Let n be the length of the old character sequence, the one + * contained in the {@code StringBuffer} just prior to execution of the + * {@code append} method. Then the character at index k in + * the new character sequence is equal to the character at index k + * in the old character sequence, if k is less than n; + * otherwise, it is equal to the character at index k-n in the + * argument {@code sb}. + * + * + * @param sb the {@code StringBuilder} to append. + * @return a reference to this object. + */ +public synchronized StringBuffer append(StringBuilder sb) { +toStringCache = null; +super.append(sb); +return this; +} + /** * Appends the specified {@code StringBuffer} to this sequence. * diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java b/src/java.base/share/classes/java/lang/StringBuilder.java index 40da2083c2..5ddd4fb5f9 100644 --- a/src/java.base/share/classes/java/lang/StringBuilder.java +++ b/src/java.base/share/classes/java/lang/StringBuilder.java @@ -199,6 +199,30 @@ public final class StringBuilder return this; } +/** + * Appends the specified {@code StringBuilder} to this sequence. + * + * The characters of the {@code StringBuilder} argument are appended, + * in order, to this sequence, increasing the + * length of this sequence by the length of the argument. + * If {@code sb} is {@code null}, then the four characters + * {@code "null"} are appended to this sequence. + * + * Let n be the length of this character sequence just prior to + * execution of the {@code append} method. Then the character at index + * k in the new character sequence is equal to the character at + * index k in the old character sequence, if k is less than + * n; otherwise, it is equal to the character at index k-n + * in the argument {@code sb}. + * + * @param sb the {@code StringBuilder} to append. + * @return a reference to this object. + */ +public StringBuilder append(StringBuilder sb) { +super.append(sb); +return this; +} + @Override public StringBuilder append(CharSequence s) { super.append(s);