Summary
Modify the specifications of StringBuilder and StringBuffer to be less restrictive about exactly when they are required to create new String instances.
Problem
Several methods that return String and CharSequence have an assertion of the form "returns a new String that...." This is unnecessarily restrictive, as there are cases where an existing String instance that has the right value might already be available. The most common case of this is the empty string literal (""), an instance of which is typically interned, which a method might want to return if it's asked to return a zero-length String. (But there might be other cases too.)
The "returns a new String" wording has been consistent in the specifications of StringBuffer (and later StringBuilder) since its introduction around JDK 1.2. A quick survey of historic JDKs revealed that they conformed to this requirement, as an expression like new StringBuilder().substring(0)
returned a new, empty String instance distinct from the interned empty String. In JDK 15 and later, however, the actual interned empty String was returned in such cases, which strictly speaking was noncompliant. This seemed also to be true in JDK 17 and JDK 21, but the implementation changed a couple times as fixes were developed and backported. (See JDK-8332282 for more history.) In that time no applications seemed to have been affected, although benchmarks have detected the changes.
Solution
Adjust the specification so that some String is returned that has the expected value, but not necessarily a "new" String.
Specification
Changes are made to the specifications of the following methods in the AbstractStringBuilder class. This is a (private) superclass of StringBuilder and StringBuffer, both of which inherit these methods and their specifications, so identical changes will appear in the public specifications in StringBuilder and StringBuffer.
/**
- * Returns a new {@code String} that contains a subsequence of
+ * Returns a {@code String} that contains a subsequence of
* characters currently contained in this character sequence. The
* substring begins at the specified index and extends to the end of
* this sequence.
*
* @param start The beginning index, inclusive.
- * @return The new string.
+ * @return A string containing the specified subsequence of characters.
* @throws StringIndexOutOfBoundsException if {@code start} is
* less than zero, or greater than the length of this object.
*/
public String substring(int start) { ... }
/**
- * Returns a new character sequence that is a subsequence of this sequence.
+ * Returns a character sequence that is a subsequence of this sequence.
*
* <p> An invocation of this method of the form
*
* <pre>{@code
* sb.subSequence(begin, end)}</pre>
*
* behaves in exactly the same way as the invocation
*
* <pre>{@code
* sb.substring(begin, end)}</pre>
...
*/
@Override
public CharSequence subSequence(int start, int end) { ... }
/**
- * Returns a new {@code String} that contains a subsequence of
+ * Returns a {@code String} that contains a subsequence of
* characters currently contained in this sequence. The
* substring begins at the specified {@code start} and
* extends to the character at index {@code end - 1}.
*
* @param start The beginning index, inclusive.
* @param end The ending index, exclusive.
- * @return The new string.
+ * @return A string containing the specified subsequence of characters.
* @throws StringIndexOutOfBoundsException if {@code start}
* or {@code end} are negative or greater than
* {@code length()}, or {@code start} is
* greater than {@code end}.
*/
public String substring(int start, int end) { ... }
/**
* Returns a string representing the data in this sequence.
- * A new {@code String} object is allocated and initialized to
- * contain the character sequence currently represented by this
- * object. This {@code String} is then returned. Subsequent
+ * The {@code String} object that is returned contains the character
+ * sequence currently represented by this object. Subsequent
* changes to this sequence do not affect the contents of the
- * {@code String}.
+ * returned {@code String}.
*
* @return a string representation of this sequence of characters.
*/
@Override
public abstract String toString();
- csr of
-
JDK-8138614 (spec str) StringBuffer and StringBuilder methods improperly require "new" String to be returned
-
- Resolved
-