Why does Java StringBuilder have a constructor for CharSequence and another one for String?
Asked Answered
O

1

15

Knowing that String implements CharSequence interface, so why does StringBuilder have a constructor for CharSequence and another one for String? No indication in the javadoc !

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {...}
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{

...

    /**
     * Constructs a string builder initialized to the contents of the
     * specified string. The initial capacity of the string builder is
     * {@code 16} plus the length of the string argument.
     *
     * @param   str   the initial contents of the buffer.
     */
    public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

    /**
     * Constructs a string builder that contains the same characters
     * as the specified {@code CharSequence}. The initial capacity of
     * the string builder is {@code 16} plus the length of the
     * {@code CharSequence} argument.
     *
     * @param      seq   the sequence to copy.
     */
    public StringBuilder(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }
...
}
Overhear answered 13/5, 2019 at 6:12 Comment(7)
String is only one implementatation of CharSequence. It makes sense to have another constructor that accepts any implementation of CharSequence e.g CharBuffer, Segment, String, StringBuffer or StringBuilder.Sneck
If you check subsequent calls, you'll see that there are different implementations of java.lang.AbstractStringBuilder.append for String and CharSequence. Seems the string version is optimized specifically.Sallie
@Sallie But the append(CharSequence s) is calling append(String str) if the charSequence is instanceof String !!Overhear
@Sneck Liskov will not be happy.Overhear
@Overhear Exactly. So they prefer the append(String) to append(CharSequence) implementation. And if you look at the actual code, you can guess with me that append(String) is optimal.Sallie
@Overhear LSP is not violated: if you passed a string to the charsequence overload, you would get the same result. Moreover, LSP doesn't apply to overloads: overloads are unrelated methods which happen to have the same name.Sandra
It's just a little performance detail. Which is important, since this class is heavily used everywhere. It's a core class and as such every detail matters. Note that, even if you do not actively use the class, Java uses it internally to replace and optimize String usages in your code.Coquetry
D
12

Optimization. If I am not mistaken, there are two implementations of append. append(String) is more efficient than append(CharSequence) where CharSequence is a string. If I had to do some extra routine to check to make sure the CharSequence is compatible with String, convert it to String, and run the append(String), that would be longer than append(String) directly. Same result. Different speed.

Deletion answered 13/5, 2019 at 6:56 Comment(4)
"StringBuilder is generally meant for strings, hence the name" StringBuilder is meant to build Strings. Its name says nothing about what it expects them to be built from.Sandra
@AndyTurner indeed, similar to how if you have some CarBuilder it doesn't necessarily have to accept cars. It needs car parts. If it does accept Car objects, it would likely be to re-use their parts.Tunesmith
The specific optimization here is that String provides a getChars method that utilizes the System.arraycopy to copy the chars from the String's internal char array directly to the StringBuilders's char array in one shot. The naive CharSequence version has to loop over the sequence calling charAt for every index.Heliotropin
@Heliotropin Yeh wasn't sure the exact implementation... just knew there was an extra routine that would be unnecessary for Strings.Deletion

© 2022 - 2024 — McMap. All rights reserved.