8317612: ChoiceFormat and MessageFormat constructors call non-final public method

Reviewed-by: naoto, lancea
This commit is contained in:
Justin Lu 2023-11-01 21:29:45 +00:00
parent f262f06c97
commit ee57e731d0
2 changed files with 50 additions and 17 deletions

View File

@ -246,6 +246,17 @@ public class ChoiceFormat extends NumberFormat {
* @see #ChoiceFormat(String) * @see #ChoiceFormat(String)
*/ */
public void applyPattern(String newPattern) { public void applyPattern(String newPattern) {
applyPatternImpl(newPattern);
}
/**
* Implementation of applying a pattern to this ChoiceFormat.
* This method processes a String pattern in accordance with the ChoiceFormat
* pattern syntax and populates the internal {@code limits} and {@code formats}
* array variables. See the {@linkplain ##patterns} section for
* further understanding of certain special characters: "#", "<", "\u2264", "|".
*/
private void applyPatternImpl(String newPattern) {
StringBuilder[] segments = new StringBuilder[2]; StringBuilder[] segments = new StringBuilder[2];
for (int i = 0; i < segments.length; ++i) { for (int i = 0; i < segments.length; ++i) {
segments[i] = new StringBuilder(); segments[i] = new StringBuilder();
@ -326,8 +337,8 @@ public class ChoiceFormat extends NumberFormat {
} }
/** /**
* {@return a pattern {@code string} that represents the the limits and formats * {@return a pattern {@code string} that represents the {@code limits} and
* of this ChoiceFormat object} * {@code formats} of this ChoiceFormat object}
* *
* The {@code string} returned is not guaranteed to be the same input * The {@code string} returned is not guaranteed to be the same input
* {@code string} passed to either {@link #applyPattern(String)} or * {@code string} passed to either {@link #applyPattern(String)} or
@ -396,7 +407,7 @@ public class ChoiceFormat extends NumberFormat {
* @see #applyPattern * @see #applyPattern
*/ */
public ChoiceFormat(String newPattern) { public ChoiceFormat(String newPattern) {
applyPattern(newPattern); applyPatternImpl(newPattern);
} }
/** /**
@ -411,11 +422,12 @@ public class ChoiceFormat extends NumberFormat {
* @see #setChoices * @see #setChoices
*/ */
public ChoiceFormat(double[] limits, String[] formats) { public ChoiceFormat(double[] limits, String[] formats) {
setChoices(limits, formats); setChoicesImpl(limits, formats);
} }
/** /**
* Set the choices to be used in formatting. * Set the choices to be used in formatting.
*
* @param limits contains the top value that you want * @param limits contains the top value that you want
* parsed with that format, and should be in ascending sorted order. When * parsed with that format, and should be in ascending sorted order. When
* formatting X, the choice will be the i, where * formatting X, the choice will be the i, where
@ -429,6 +441,14 @@ public class ChoiceFormat extends NumberFormat {
* and {@code formats} are not equal * and {@code formats} are not equal
*/ */
public void setChoices(double[] limits, String[] formats) { public void setChoices(double[] limits, String[] formats) {
setChoicesImpl(limits, formats);
}
/**
* Implementation of populating the {@code limits} and
* {@code formats} of this ChoiceFormat. Defensive copies are made.
*/
private void setChoicesImpl(double[] limits, String[] formats) {
if (limits.length != formats.length) { if (limits.length != formats.length) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Input arrays must be of the same length."); "Input arrays must be of the same length.");
@ -441,16 +461,14 @@ public class ChoiceFormat extends NumberFormat {
* {@return the limits of this ChoiceFormat} * {@return the limits of this ChoiceFormat}
*/ */
public double[] getLimits() { public double[] getLimits() {
double[] newLimits = Arrays.copyOf(choiceLimits, choiceLimits.length); return Arrays.copyOf(choiceLimits, choiceLimits.length);
return newLimits;
} }
/** /**
* {@return the formats of this ChoiceFormat} * {@return the formats of this ChoiceFormat}
*/ */
public Object[] getFormats() { public Object[] getFormats() {
Object[] newFormats = Arrays.copyOf(choiceFormats, choiceFormats.length); return Arrays.copyOf(choiceFormats, choiceFormats.length);
return newFormats;
} }
// Overrides // Overrides

View File

@ -371,7 +371,7 @@ public class MessageFormat extends Format {
* The constructor first sets the locale, then parses the pattern and * The constructor first sets the locale, then parses the pattern and
* creates a list of subformats for the format elements contained in it. * creates a list of subformats for the format elements contained in it.
* Patterns and their interpretation are specified in the * Patterns and their interpretation are specified in the
* <a href="#patterns">class description</a>. * {@linkplain ##patterns class description}.
* *
* @param pattern the pattern for this message format * @param pattern the pattern for this message format
* @throws IllegalArgumentException if the pattern is invalid * @throws IllegalArgumentException if the pattern is invalid
@ -380,7 +380,7 @@ public class MessageFormat extends Format {
*/ */
public MessageFormat(String pattern) { public MessageFormat(String pattern) {
this.locale = Locale.getDefault(Locale.Category.FORMAT); this.locale = Locale.getDefault(Locale.Category.FORMAT);
applyPattern(pattern); applyPatternImpl(pattern);
} }
/** /**
@ -389,7 +389,7 @@ public class MessageFormat extends Format {
* The constructor first sets the locale, then parses the pattern and * The constructor first sets the locale, then parses the pattern and
* creates a list of subformats for the format elements contained in it. * creates a list of subformats for the format elements contained in it.
* Patterns and their interpretation are specified in the * Patterns and their interpretation are specified in the
* <a href="#patterns">class description</a>. * {@linkplain ##patterns class description}.
* *
* @implSpec The default implementation throws a * @implSpec The default implementation throws a
* {@code NullPointerException} if {@code locale} is {@code null} * {@code NullPointerException} if {@code locale} is {@code null}
@ -408,7 +408,7 @@ public class MessageFormat extends Format {
*/ */
public MessageFormat(String pattern, Locale locale) { public MessageFormat(String pattern, Locale locale) {
this.locale = locale; this.locale = locale;
applyPattern(pattern); applyPatternImpl(pattern);
} }
/** /**
@ -447,15 +447,29 @@ public class MessageFormat extends Format {
* The method parses the pattern and creates a list of subformats * The method parses the pattern and creates a list of subformats
* for the format elements contained in it. * for the format elements contained in it.
* Patterns and their interpretation are specified in the * Patterns and their interpretation are specified in the
* <a href="#patterns">class description</a>. * {@linkplain ##patterns class description}.
* *
* @param pattern the pattern for this message format * @param pattern the pattern for this message format
* @throws IllegalArgumentException if the pattern is invalid * @throws IllegalArgumentException if the pattern is invalid
* @throws NullPointerException if {@code pattern} is * @throws NullPointerException if {@code pattern} is
* {@code null} * {@code null}
*/ */
@SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
public void applyPattern(String pattern) { public void applyPattern(String pattern) {
applyPatternImpl(pattern);
}
/**
* Implementation of applying a pattern to this MessageFormat.
* This method processes a String pattern in accordance with the MessageFormat
* pattern syntax and sets the internal {@code pattern} variable as well as
* populating the {@code formats} array with the subformats defined in the
* pattern. See the {@linkplain ##patterns} section for further understanding
* of certain special characters: "{", "}", ",". See {@linkplain
* ##makeFormat(int, int, StringBuilder[])} for the implementation of setting
* a subformat.
*/
@SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
private void applyPatternImpl(String pattern) {
StringBuilder[] segments = new StringBuilder[4]; StringBuilder[] segments = new StringBuilder[4];
// Allocate only segments[SEG_RAW] here. The rest are // Allocate only segments[SEG_RAW] here. The rest are
// allocated on demand. // allocated on demand.
@ -509,6 +523,7 @@ public class MessageFormat extends Format {
case '}': case '}':
if (braceStack == 0) { if (braceStack == 0) {
part = SEG_RAW; part = SEG_RAW;
// Set the subformat
makeFormat(i, formatNumber, segments); makeFormat(i, formatNumber, segments);
formatNumber++; formatNumber++;
// throw away other segments // throw away other segments
@ -1592,7 +1607,7 @@ public class MessageFormat extends Format {
formats[offsetNumber] = newFormat; formats[offsetNumber] = newFormat;
} }
private static final int findKeyword(String s, String[] list) { private static int findKeyword(String s, String[] list) {
for (int i = 0; i < list.length; ++i) { for (int i = 0; i < list.length; ++i) {
if (s.equals(list[i])) if (s.equals(list[i]))
return i; return i;
@ -1609,7 +1624,7 @@ public class MessageFormat extends Format {
return -1; return -1;
} }
private static final void copyAndFixQuotes(String source, int start, int end, private static void copyAndFixQuotes(String source, int start, int end,
StringBuilder target) { StringBuilder target) {
boolean quoted = false; boolean quoted = false;