1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 /*
28  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
29  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
30  *
31  *   The original version of this source code and documentation is copyrighted
32  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
33  * materials are provided under terms of a License Agreement between Taligent
34  * and Sun. This technology is protected by multiple US and International
35  * patents. This notice and attribution to Taligent may not be removed.
36  *   Taligent is a registered trademark of Taligent, Inc.
37  *
38  */
39 
40 package java.text;
41 
42 import java.io.InvalidObjectException;
43 import java.io.IOException;
44 import java.io.ObjectInputStream;
45 import java.io.ObjectOutputStream;
46 import java.math.BigInteger;
47 import java.math.RoundingMode;
48 import java.util.Currency;
49 import java.util.HashMap;
50 import java.util.Locale;
51 import java.util.Map;
52 import java.util.Objects;
53 import java.util.concurrent.atomic.AtomicInteger;
54 import java.util.concurrent.atomic.AtomicLong;
55 
56 import libcore.icu.DecimalFormatData;
57 import libcore.icu.ICU;
58 import libcore.icu.LocaleData;
59 
60 // Android-removed: Remove javadoc related to "rg" Locale extension.
61 // The "rg" extension isn't supported until https://unicode-org.atlassian.net/browse/ICU-21831
62 // is resolved, because java.text.* stack relies on ICU on resource resolution.
63 /**
64  * {@code NumberFormat} is the abstract base class for all number
65  * formats. This class provides the interface for formatting and parsing
66  * numbers. {@code NumberFormat} also provides methods for determining
67  * which locales have number formats, and what their names are.
68  *
69  * <p>
70  * {@code NumberFormat} helps you to format and parse numbers for any locale.
71  * Your code can be completely independent of the locale conventions for
72  * decimal points, thousands-separators, or even the particular decimal
73  * digits used, or whether the number format is even decimal.
74  *
75  * <p>
76  * To format a number for the current Locale, use one of the factory
77  * class methods:
78  * <blockquote>
79  * <pre>{@code
80  * myString = NumberFormat.getInstance().format(myNumber);
81  * }</pre>
82  * </blockquote>
83  * If you are formatting multiple numbers, it is
84  * more efficient to get the format and use it multiple times so that
85  * the system doesn't have to fetch the information about the local
86  * language and country conventions multiple times.
87  * <blockquote>
88  * <pre>{@code
89  * NumberFormat nf = NumberFormat.getInstance();
90  * for (int i = 0; i < myNumber.length; ++i) {
91  *     output.println(nf.format(myNumber[i]) + "; ");
92  * }
93  * }</pre>
94  * </blockquote>
95  * To format a number for a different Locale, specify it in the
96  * call to {@code getInstance}.
97  * <blockquote>
98  * <pre>{@code
99  * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
100  * }</pre>
101  * </blockquote>
102  *
103  * <p>If the locale contains "nu" (numbers)
104  * <a href="../util/Locale.html#def_locale_extension">Unicode extensions</a>,
105  * the decimal digits, and/or the country used for formatting are overridden.
106  *
107  * <p>You can also use a {@code NumberFormat} to parse numbers:
108  * <blockquote>
109  * <pre>{@code
110  * myNumber = nf.parse(myString);
111  * }</pre>
112  * </blockquote>
113  * Use {@code getInstance} or {@code getNumberInstance} to get the
114  * normal number format. Use {@code getIntegerInstance} to get an
115  * integer number format. Use {@code getCurrencyInstance} to get the
116  * currency number format. Use {@code getCompactNumberInstance} to get the
117  * compact number format to format a number in shorter form. For example,
118  * {@code 2000} can be formatted as {@code "2K"} in
119  * {@link java.util.Locale#US US locale}. Use {@code getPercentInstance}
120  * to get a format for displaying percentages. With this format, a fraction
121  * like 0.53 is displayed as 53%.
122  *
123  * <p>
124  * You can also control the display of numbers with such methods as
125  * {@code setMinimumFractionDigits}.
126  * If you want even more control over the format or parsing,
127  * or want to give your users more control,
128  * you can try casting the {@code NumberFormat} you get from the factory methods
129  * to a {@code DecimalFormat} or {@code CompactNumberFormat} depending on
130  * the factory method used. This will work for the vast majority of locales;
131  * just remember to put it in a {@code try} block in case you encounter
132  * an unusual one.
133  *
134  * <p>
135  * NumberFormat and DecimalFormat are designed such that some controls
136  * work for formatting and others work for parsing.  The following is
137  * the detailed description for each these control methods,
138  * <p>
139  * setParseIntegerOnly : only affects parsing, e.g.
140  * if true,  "3456.78" &rarr; 3456 (and leaves the parse position just after index 6)
141  * if false, "3456.78" &rarr; 3456.78 (and leaves the parse position just after index 8)
142  * This is independent of formatting.  If you want to not show a decimal point
143  * where there might be no digits after the decimal point, use
144  * setDecimalSeparatorAlwaysShown.
145  * <p>
146  * setDecimalSeparatorAlwaysShown : only affects formatting, and only where
147  * there might be no digits after the decimal point, such as with a pattern
148  * like "#,##0.##", e.g.,
149  * if true,  3456.00 &rarr; "3,456."
150  * if false, 3456.00 &rarr; "3456"
151  * This is independent of parsing.  If you want parsing to stop at the decimal
152  * point, use setParseIntegerOnly.
153  *
154  * <p>
155  * You can also use forms of the {@code parse} and {@code format}
156  * methods with {@code ParsePosition} and {@code FieldPosition} to
157  * allow you to:
158  * <ul>
159  * <li> progressively parse through pieces of a string
160  * <li> align the decimal point and other areas
161  * </ul>
162  * For example, you can align numbers in two ways:
163  * <ol>
164  * <li> If you are using a monospaced font with spacing for alignment,
165  *      you can pass the {@code FieldPosition} in your format call, with
166  *      {@code field} = {@code INTEGER_FIELD}. On output,
167  *      {@code getEndIndex} will be set to the offset between the
168  *      last character of the integer and the decimal. Add
169  *      (desiredSpaceCount - getEndIndex) spaces at the front of the string.
170  *
171  * <li> If you are using proportional fonts,
172  *      instead of padding with spaces, measure the width
173  *      of the string in pixels from the start to {@code getEndIndex}.
174  *      Then move the pen by
175  *      (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
176  *      It also works where there is no decimal, but possibly additional
177  *      characters at the end, e.g., with parentheses in negative
178  *      numbers: "(12)" for -12.
179  * </ol>
180  *
181  * <h2><a id="synchronization">Synchronization</a></h2>
182  *
183  * <p>
184  * Number formats are generally not synchronized.
185  * It is recommended to create separate format instances for each thread.
186  * If multiple threads access a format concurrently, it must be synchronized
187  * externally.
188  *
189  * @implSpec The {@link #format(double, StringBuffer, FieldPosition)},
190  * {@link #format(long, StringBuffer, FieldPosition)} and
191  * {@link #parse(String, ParsePosition)} methods may throw
192  * {@code NullPointerException}, if any of their parameter is {@code null}.
193  * The subclass may provide its own implementation and specification about
194  * {@code NullPointerException}.
195  *
196  * <p>
197  * The default implementation provides rounding modes defined
198  * in {@link java.math.RoundingMode} for formatting numbers. It
199  * uses the {@linkplain java.math.RoundingMode#HALF_EVEN
200  * round half-even algorithm}. To change the rounding mode use
201  * {@link #setRoundingMode(java.math.RoundingMode) setRoundingMode}.
202  * The {@code NumberFormat} returned by the static factory methods is
203  * configured to round floating point numbers using half-even
204  * rounding (see {@link java.math.RoundingMode#HALF_EVEN
205  * RoundingMode.HALF_EVEN}) for formatting.
206  *
207  * @see          DecimalFormat
208  * @see          ChoiceFormat
209  * @author       Mark Davis
210  * @author       Helena Shih
211  * @since 1.1
212  */
213 public abstract class NumberFormat extends Format  {
214 
215     /**
216      * Field constant used to construct a FieldPosition object. Signifies that
217      * the position of the integer part of a formatted number should be returned.
218      * @see java.text.FieldPosition
219      */
220     public static final int INTEGER_FIELD = 0;
221 
222     /**
223      * Field constant used to construct a FieldPosition object. Signifies that
224      * the position of the fraction part of a formatted number should be returned.
225      * @see java.text.FieldPosition
226      */
227     public static final int FRACTION_FIELD = 1;
228 
229     /**
230      * Sole constructor.  (For invocation by subclass constructors, typically
231      * implicit.)
232      */
NumberFormat()233     protected NumberFormat() {
234     }
235 
236     /**
237      * Formats a number and appends the resulting text to the given string
238      * buffer.
239      * The number can be of any subclass of {@link java.lang.Number}.
240      * <p>
241      * This implementation extracts the number's value using
242      * {@link java.lang.Number#longValue()} for all integral type values that
243      * can be converted to {@code long} without loss of information,
244      * including {@code BigInteger} values with a
245      * {@link java.math.BigInteger#bitLength() bit length} of less than 64,
246      * and {@link java.lang.Number#doubleValue()} for all other types. It
247      * then calls
248      * {@link #format(long,java.lang.StringBuffer,java.text.FieldPosition)}
249      * or {@link #format(double,java.lang.StringBuffer,java.text.FieldPosition)}.
250      * This may result in loss of magnitude information and precision for
251      * {@code BigInteger} and {@code BigDecimal} values.
252      * @param number     the number to format
253      * @param toAppendTo the {@code StringBuffer} to which the formatted
254      *                   text is to be appended
255      * @param pos        keeps track on the position of the field within the
256      *                   returned string. For example, for formatting a number
257      *                   {@code 1234567.89} in {@code Locale.US} locale,
258      *                   if the given {@code fieldPosition} is
259      *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
260      *                   and end index of {@code fieldPosition} will be set
261      *                   to 0 and 9, respectively for the output string
262      *                   {@code 1,234,567.89}.
263      * @return           the value passed in as {@code toAppendTo}
264      * @throws           IllegalArgumentException if {@code number} is
265      *                   null or not an instance of {@code Number}.
266      * @throws           NullPointerException if {@code toAppendTo} or
267      *                   {@code pos} is null
268      * @throws           ArithmeticException if rounding is needed with rounding
269      *                   mode being set to RoundingMode.UNNECESSARY
270      * @see              java.text.FieldPosition
271      */
272     @Override
format(Object number, StringBuffer toAppendTo, FieldPosition pos)273     public StringBuffer format(Object number,
274                                StringBuffer toAppendTo,
275                                FieldPosition pos) {
276         if (number instanceof Long || number instanceof Integer ||
277             number instanceof Short || number instanceof Byte ||
278             number instanceof AtomicInteger || number instanceof AtomicLong ||
279             (number instanceof BigInteger &&
280              ((BigInteger)number).bitLength() < 64)) {
281             return format(((Number)number).longValue(), toAppendTo, pos);
282         } else if (number instanceof Number) {
283             return format(((Number)number).doubleValue(), toAppendTo, pos);
284         } else {
285             throw new IllegalArgumentException("Cannot format given Object as a Number");
286         }
287     }
288 
289     /**
290      * Parses text from a string to produce a {@code Number}.
291      * <p>
292      * The method attempts to parse text starting at the index given by
293      * {@code pos}.
294      * If parsing succeeds, then the index of {@code pos} is updated
295      * to the index after the last character used (parsing does not necessarily
296      * use all characters up to the end of the string), and the parsed
297      * number is returned. The updated {@code pos} can be used to
298      * indicate the starting point for the next call to this method.
299      * If an error occurs, then the index of {@code pos} is not
300      * changed, the error index of {@code pos} is set to the index of
301      * the character where the error occurred, and null is returned.
302      * <p>
303      * See the {@link #parse(String, ParsePosition)} method for more information
304      * on number parsing.
305      *
306      * @param source A {@code String}, part of which should be parsed.
307      * @param pos A {@code ParsePosition} object with index and error
308      *            index information as described above.
309      * @return A {@code Number} parsed from the string. In case of
310      *         error, returns null.
311      * @throws NullPointerException if {@code source} or {@code pos} is null.
312      */
313     @Override
parseObject(String source, ParsePosition pos)314     public final Object parseObject(String source, ParsePosition pos) {
315         return parse(source, pos);
316     }
317 
318     /**
319      * Specialization of format.
320      *
321      * @param number the double number to format
322      * @return the formatted String
323      * @throws           ArithmeticException if rounding is needed with rounding
324      *                   mode being set to RoundingMode.UNNECESSARY
325      * @see java.text.Format#format
326      */
format(double number)327     public final String format(double number) {
328         // Android-removed: fast-path code.
329         return format(number, new StringBuffer(),
330                       DontCareFieldPosition.INSTANCE).toString();
331     }
332 
333     // Android-removed: fastFormat method.
334 
335     /**
336      * Specialization of format.
337      *
338      * @param number the long number to format
339      * @return the formatted String
340      * @throws           ArithmeticException if rounding is needed with rounding
341      *                   mode being set to RoundingMode.UNNECESSARY
342      * @see java.text.Format#format
343      */
format(long number)344     public final String format(long number) {
345         return format(number, new StringBuffer(),
346                       DontCareFieldPosition.INSTANCE).toString();
347     }
348 
349     /**
350      * Specialization of format.
351      *
352      * @param number     the double number to format
353      * @param toAppendTo the StringBuffer to which the formatted text is to be
354      *                   appended
355      * @param pos        keeps track on the position of the field within the
356      *                   returned string. For example, for formatting a number
357      *                   {@code 1234567.89} in {@code Locale.US} locale,
358      *                   if the given {@code fieldPosition} is
359      *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
360      *                   and end index of {@code fieldPosition} will be set
361      *                   to 0 and 9, respectively for the output string
362      *                   {@code 1,234,567.89}.
363      * @return the formatted StringBuffer
364      * @throws           ArithmeticException if rounding is needed with rounding
365      *                   mode being set to RoundingMode.UNNECESSARY
366      * @see java.text.Format#format
367      */
format(double number, StringBuffer toAppendTo, FieldPosition pos)368     public abstract StringBuffer format(double number,
369                                         StringBuffer toAppendTo,
370                                         FieldPosition pos);
371 
372     /**
373      * Specialization of format.
374      *
375      * @param number     the long number to format
376      * @param toAppendTo the StringBuffer to which the formatted text is to be
377      *                   appended
378      * @param pos        keeps track on the position of the field within the
379      *                   returned string. For example, for formatting a number
380      *                   {@code 123456789} in {@code Locale.US} locale,
381      *                   if the given {@code fieldPosition} is
382      *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
383      *                   and end index of {@code fieldPosition} will be set
384      *                   to 0 and 11, respectively for the output string
385      *                   {@code 123,456,789}.
386      * @return the formatted StringBuffer
387      * @throws           ArithmeticException if rounding is needed with rounding
388      *                   mode being set to RoundingMode.UNNECESSARY
389      * @see java.text.Format#format
390      */
format(long number, StringBuffer toAppendTo, FieldPosition pos)391     public abstract StringBuffer format(long number,
392                                         StringBuffer toAppendTo,
393                                         FieldPosition pos);
394 
395     // Android-changed: Added a warning of deserialization.
396     /**
397      * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
398      * Long.MAX_VALUE] and with no decimals), otherwise a Double.
399      * If IntegerOnly is set, will stop at a decimal
400      * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
401      * after the 1).
402      * Does not throw an exception; if no object can be parsed, index is
403      * unchanged!
404      *
405      * <p> <b>WARNING:</b> Don't use this method to deserialize a number. The underlying localized
406      * number format and parsing behaviors can change across Android versions as common usage
407      * in the locale changes. Consider using the parse methods in the boxed types,
408      * e.g. {@link Long#parseLong(String)}, or {@link java.math.BigDecimal} for deserializing
409      * a locale-independent decimal number.</p>
410      *
411      * @param source the String to parse
412      * @param parsePosition the parse position
413      * @return the parsed value
414      * @see java.text.NumberFormat#isParseIntegerOnly
415      * @see java.text.Format#parseObject
416      */
parse(String source, ParsePosition parsePosition)417     public abstract Number parse(String source, ParsePosition parsePosition);
418 
419     // Android-changed: Added a warning of deserialization.
420     /**
421      * Parses text from the beginning of the given string to produce a number.
422      * The method may not use the entire text of the given string.
423      * <p>
424      * See the {@link #parse(String, ParsePosition)} method for more information
425      * on number parsing.
426      *
427      * <p> <b>WARNING:</b> Don't use this method to deserialize a number. The underlying localized
428      * number format and parsing behaviors can change across Android versions as common usage
429      * in the locale changes. Consider using the parse methods in the boxed types,
430      * e.g. {@link Long#parseLong(String)}, or {@link java.math.BigDecimal} for deserializing
431      * a locale-independent decimal number.</p>
432      *
433      * @param source A {@code String} whose beginning should be parsed.
434      * @return A {@code Number} parsed from the string.
435      * @throws    ParseException if the beginning of the specified string
436      *            cannot be parsed.
437      */
parse(String source)438     public Number parse(String source) throws ParseException {
439         ParsePosition parsePosition = new ParsePosition(0);
440         Number result = parse(source, parsePosition);
441         if (parsePosition.index == 0) {
442             throw new ParseException("Unparseable number: \"" + source + "\"",
443                                      parsePosition.errorIndex);
444         }
445         return result;
446     }
447 
448     /**
449      * Returns true if this format will parse numbers as integers only.
450      * For example in the English locale, with ParseIntegerOnly true, the
451      * string "1234." would be parsed as the integer value 1234 and parsing
452      * would stop at the "." character.  Of course, the exact format accepted
453      * by the parse operation is locale dependent and determined by sub-classes
454      * of NumberFormat.
455      *
456      * @return {@code true} if numbers should be parsed as integers only;
457      *         {@code false} otherwise
458      */
isParseIntegerOnly()459     public boolean isParseIntegerOnly() {
460         return parseIntegerOnly;
461     }
462 
463     /**
464      * Sets whether or not numbers should be parsed as integers only.
465      *
466      * @param value {@code true} if numbers should be parsed as integers only;
467      *              {@code false} otherwise
468      * @see #isParseIntegerOnly
469      */
setParseIntegerOnly(boolean value)470     public void setParseIntegerOnly(boolean value) {
471         parseIntegerOnly = value;
472     }
473 
474     //============== Locale Stuff =====================
475 
476     /**
477      * Returns a general-purpose number format for the current default
478      * {@link java.util.Locale.Category#FORMAT FORMAT} locale.
479      * This is the same as calling
480      * {@link #getNumberInstance() getNumberInstance()}.
481      *
482      * @return the {@code NumberFormat} instance for general-purpose number
483      * formatting
484      */
getInstance()485     public static final NumberFormat getInstance() {
486         return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, NUMBERSTYLE);
487     }
488 
489     /**
490      * Returns a general-purpose number format for the specified locale.
491      * This is the same as calling
492      * {@link #getNumberInstance(java.util.Locale) getNumberInstance(inLocale)}.
493      *
494      * @param inLocale the desired locale
495      * @return the {@code NumberFormat} instance for general-purpose number
496      * formatting
497      */
getInstance(Locale inLocale)498     public static NumberFormat getInstance(Locale inLocale) {
499         return getInstance(inLocale, null, NUMBERSTYLE);
500     }
501 
502     /**
503      * Returns a general-purpose number format for the current default
504      * {@link java.util.Locale.Category#FORMAT FORMAT} locale.
505      * <p>This is equivalent to calling
506      * {@link #getNumberInstance(Locale)
507      *     getNumberInstance(Locale.getDefault(Locale.Category.FORMAT))}.
508      *
509      * @return the {@code NumberFormat} instance for general-purpose number
510      * formatting
511      * @see java.util.Locale#getDefault(java.util.Locale.Category)
512      * @see java.util.Locale.Category#FORMAT
513      */
getNumberInstance()514     public static final NumberFormat getNumberInstance() {
515         return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, NUMBERSTYLE);
516     }
517 
518     /**
519      * Returns a general-purpose number format for the specified locale.
520      *
521      * @param inLocale the desired locale
522      * @return the {@code NumberFormat} instance for general-purpose number
523      * formatting
524      */
getNumberInstance(Locale inLocale)525     public static NumberFormat getNumberInstance(Locale inLocale) {
526         return getInstance(inLocale, null, NUMBERSTYLE);
527     }
528 
529     /**
530      * Returns an integer number format for the current default
531      * {@link java.util.Locale.Category#FORMAT FORMAT} locale. The
532      * returned number format is configured to round floating point numbers
533      * to the nearest integer using half-even rounding (see {@link
534      * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting,
535      * and to parse only the integer part of an input string (see {@link
536      * #isParseIntegerOnly isParseIntegerOnly}).
537      * <p>This is equivalent to calling
538      * {@link #getIntegerInstance(Locale)
539      *     getIntegerInstance(Locale.getDefault(Locale.Category.FORMAT))}.
540      *
541      * @see #getRoundingMode()
542      * @see java.util.Locale#getDefault(java.util.Locale.Category)
543      * @see java.util.Locale.Category#FORMAT
544      * @return a number format for integer values
545      * @since 1.4
546      */
getIntegerInstance()547     public static final NumberFormat getIntegerInstance() {
548         return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, INTEGERSTYLE);
549     }
550 
551     /**
552      * Returns an integer number format for the specified locale. The
553      * returned number format is configured to round floating point numbers
554      * to the nearest integer using half-even rounding (see {@link
555      * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting,
556      * and to parse only the integer part of an input string (see {@link
557      * #isParseIntegerOnly isParseIntegerOnly}).
558      *
559      * @param inLocale the desired locale
560      * @see #getRoundingMode()
561      * @return a number format for integer values
562      * @since 1.4
563      */
getIntegerInstance(Locale inLocale)564     public static NumberFormat getIntegerInstance(Locale inLocale) {
565         return getInstance(inLocale, null, INTEGERSTYLE);
566     }
567 
568     /**
569      * Returns a currency format for the current default
570      * {@link java.util.Locale.Category#FORMAT FORMAT} locale.
571      * <p>This is equivalent to calling
572      * {@link #getCurrencyInstance(Locale)
573      *     getCurrencyInstance(Locale.getDefault(Locale.Category.FORMAT))}.
574      *
575      * @return the {@code NumberFormat} instance for currency formatting
576      * @see java.util.Locale#getDefault(java.util.Locale.Category)
577      * @see java.util.Locale.Category#FORMAT
578      */
getCurrencyInstance()579     public static final NumberFormat getCurrencyInstance() {
580         return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, CURRENCYSTYLE);
581     }
582 
583     /**
584      * Returns a currency format for the specified locale.
585      *
586      * <p>If the specified locale contains the "{@code cf}" (
587      * <a href="https://www.unicode.org/reports/tr35/tr35.html#UnicodeCurrencyFormatIdentifier">
588      * currency format style</a>)
589      * <a href="../util/Locale.html#def_locale_extension">Unicode extension</a>,
590      * the returned currency format uses the style if it is available.
591      * Otherwise, the style uses the default "{@code standard}" currency format.
592      * For example, if the style designates "{@code account}", negative
593      * currency amounts use a pair of parentheses in some locales.
594      *
595      * @param inLocale the desired locale
596      * @return the {@code NumberFormat} instance for currency formatting
597      */
getCurrencyInstance(Locale inLocale)598     public static NumberFormat getCurrencyInstance(Locale inLocale) {
599         return getInstance(inLocale, null, CURRENCYSTYLE);
600     }
601 
602     /**
603      * Returns a percentage format for the current default
604      * {@link java.util.Locale.Category#FORMAT FORMAT} locale.
605      * <p>This is equivalent to calling
606      * {@link #getPercentInstance(Locale)
607      *     getPercentInstance(Locale.getDefault(Locale.Category.FORMAT))}.
608      *
609      * @return the {@code NumberFormat} instance for percentage formatting
610      * @see java.util.Locale#getDefault(java.util.Locale.Category)
611      * @see java.util.Locale.Category#FORMAT
612      */
getPercentInstance()613     public static final NumberFormat getPercentInstance() {
614         return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, PERCENTSTYLE);
615     }
616 
617     /**
618      * Returns a percentage format for the specified locale.
619      *
620      * @param inLocale the desired locale
621      * @return the {@code NumberFormat} instance for percentage formatting
622      */
getPercentInstance(Locale inLocale)623     public static NumberFormat getPercentInstance(Locale inLocale) {
624         return getInstance(inLocale, null, PERCENTSTYLE);
625     }
626 
627     // BEGIN Android-removed: non-API methods getScientificInstance([Locale]).
628     /**
629      * Returns a scientific format for the current default locale.
630      *
631     /*public* static final NumberFormat getScientificInstance() {
632         return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, SCIENTIFICSTYLE);
633     }
634 
635     /**
636      * Returns a scientific format for the specified locale.
637      *
638      * @param inLocale the desired locale
639      *
640     /*public* static NumberFormat getScientificInstance(Locale inLocale) {
641         return getInstance(inLocale, null, SCIENTIFICSTYLE);
642     }
643     */
644     // END Android-removed: non-API methods getScientificInstance([Locale]).
645 
646     // BEGIN Android-removed: Remove unsupported CompactNumberFormat.
647     /*
648      * Returns a compact number format for the default
649      * {@link java.util.Locale.Category#FORMAT FORMAT} locale with
650      * {@link NumberFormat.Style#SHORT "SHORT"} format style.
651      *
652      * @return A {@code NumberFormat} instance for compact number
653      *         formatting
654      *
655      * @see CompactNumberFormat
656      * @see NumberFormat.Style
657      * @see java.util.Locale#getDefault(java.util.Locale.Category)
658      * @see java.util.Locale.Category#FORMAT
659      * @since 12
660      *
661     public static NumberFormat getCompactNumberInstance() {
662         return getInstance(Locale.getDefault(
663                 Locale.Category.FORMAT), NumberFormat.Style.SHORT, COMPACTSTYLE);
664     }
665 
666     /*
667      * Returns a compact number format for the specified {@link java.util.Locale locale}
668      * and {@link NumberFormat.Style formatStyle}.
669      *
670      * @param locale the desired locale
671      * @param formatStyle the style for formatting a number
672      * @return A {@code NumberFormat} instance for compact number
673      *         formatting
674      * @throws NullPointerException if {@code locale} or {@code formatStyle}
675      *                              is {@code null}
676      *
677      * @see CompactNumberFormat
678      * @see NumberFormat.Style
679      * @see java.util.Locale
680      * @since 12
681      *
682     public static NumberFormat getCompactNumberInstance(Locale locale,
683             NumberFormat.Style formatStyle) {
684 
685         Objects.requireNonNull(locale);
686         Objects.requireNonNull(formatStyle);
687         return getInstance(locale, formatStyle, COMPACTSTYLE);
688     }
689     // END Android-removed: Remove unsupprted CompactNumberFormat.
690 
691     // Android-changed: Removed reference to NumberFormatProvider.
692     /**
693      * Returns an array of all locales for which the
694      * {@code get*Instance} methods of this class can return
695      * localized instances.
696      * It must contain at least a {@code Locale} instance equal to
697      * {@link java.util.Locale#US Locale.US}.
698      *
699      * @return An array of locales for which localized
700      *         {@code NumberFormat} instances are available.
701      */
getAvailableLocales()702     public static Locale[] getAvailableLocales() {
703         // Android-changed: Removed used of NumberFormatProvider. Switched to use ICU.
704         return ICU.getAvailableLocales();
705     }
706 
707     /**
708      * Overrides hashCode.
709      */
710     @Override
hashCode()711     public int hashCode() {
712         return maximumIntegerDigits * 37 + maxFractionDigits;
713         // just enough fields for a reasonable distribution
714     }
715 
716     /**
717      * Overrides equals.
718      */
719     @Override
equals(Object obj)720     public boolean equals(Object obj) {
721         if (obj == null) {
722             return false;
723         }
724         if (this == obj) {
725             return true;
726         }
727         if (getClass() != obj.getClass()) {
728             return false;
729         }
730         NumberFormat other = (NumberFormat) obj;
731         return (maximumIntegerDigits == other.maximumIntegerDigits
732             && minimumIntegerDigits == other.minimumIntegerDigits
733             && maximumFractionDigits == other.maximumFractionDigits
734             && minimumFractionDigits == other.minimumFractionDigits
735             && groupingUsed == other.groupingUsed
736             && parseIntegerOnly == other.parseIntegerOnly);
737     }
738 
739     /**
740      * Overrides Cloneable.
741      */
742     @Override
clone()743     public Object clone() {
744         NumberFormat other = (NumberFormat) super.clone();
745         return other;
746     }
747 
748     /**
749      * Returns true if grouping is used in this format. For example, in the
750      * English locale, with grouping on, the number 1234567 might be formatted
751      * as "1,234,567". The grouping separator as well as the size of each group
752      * is locale dependent and is determined by sub-classes of NumberFormat.
753      *
754      * @return {@code true} if grouping is used;
755      *         {@code false} otherwise
756      * @see #setGroupingUsed
757      */
isGroupingUsed()758     public boolean isGroupingUsed() {
759         return groupingUsed;
760     }
761 
762     /**
763      * Set whether or not grouping will be used in this format.
764      *
765      * @param newValue {@code true} if grouping is used;
766      *                 {@code false} otherwise
767      * @see #isGroupingUsed
768      */
setGroupingUsed(boolean newValue)769     public void setGroupingUsed(boolean newValue) {
770         groupingUsed = newValue;
771     }
772 
773     /**
774      * Returns the maximum number of digits allowed in the integer portion of a
775      * number.
776      *
777      * @return the maximum number of digits
778      * @see #setMaximumIntegerDigits
779      */
getMaximumIntegerDigits()780     public int getMaximumIntegerDigits() {
781         return maximumIntegerDigits;
782     }
783 
784     /**
785      * Sets the maximum number of digits allowed in the integer portion of a
786      * number. maximumIntegerDigits must be &ge; minimumIntegerDigits.  If the
787      * new value for maximumIntegerDigits is less than the current value
788      * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
789      * the new value.
790      *
791      * @param newValue the maximum number of integer digits to be shown; if
792      * less than zero, then zero is used. The concrete subclass may enforce an
793      * upper limit to this value appropriate to the numeric type being formatted.
794      * @see #getMaximumIntegerDigits
795      */
setMaximumIntegerDigits(int newValue)796     public void setMaximumIntegerDigits(int newValue) {
797         maximumIntegerDigits = Math.max(0,newValue);
798         if (minimumIntegerDigits > maximumIntegerDigits) {
799             minimumIntegerDigits = maximumIntegerDigits;
800         }
801     }
802 
803     /**
804      * Returns the minimum number of digits allowed in the integer portion of a
805      * number.
806      *
807      * @return the minimum number of digits
808      * @see #setMinimumIntegerDigits
809      */
getMinimumIntegerDigits()810     public int getMinimumIntegerDigits() {
811         return minimumIntegerDigits;
812     }
813 
814     /**
815      * Sets the minimum number of digits allowed in the integer portion of a
816      * number. minimumIntegerDigits must be &le; maximumIntegerDigits.  If the
817      * new value for minimumIntegerDigits exceeds the current value
818      * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
819      * the new value
820      *
821      * @param newValue the minimum number of integer digits to be shown; if
822      * less than zero, then zero is used. The concrete subclass may enforce an
823      * upper limit to this value appropriate to the numeric type being formatted.
824      * @see #getMinimumIntegerDigits
825      */
setMinimumIntegerDigits(int newValue)826     public void setMinimumIntegerDigits(int newValue) {
827         minimumIntegerDigits = Math.max(0,newValue);
828         if (minimumIntegerDigits > maximumIntegerDigits) {
829             maximumIntegerDigits = minimumIntegerDigits;
830         }
831     }
832 
833     /**
834      * Returns the maximum number of digits allowed in the fraction portion of a
835      * number.
836      *
837      * @return the maximum number of digits.
838      * @see #setMaximumFractionDigits
839      */
getMaximumFractionDigits()840     public int getMaximumFractionDigits() {
841         return maximumFractionDigits;
842     }
843 
844     /**
845      * Sets the maximum number of digits allowed in the fraction portion of a
846      * number. maximumFractionDigits must be &ge; minimumFractionDigits.  If the
847      * new value for maximumFractionDigits is less than the current value
848      * of minimumFractionDigits, then minimumFractionDigits will also be set to
849      * the new value.
850      *
851      * @param newValue the maximum number of fraction digits to be shown; if
852      * less than zero, then zero is used. The concrete subclass may enforce an
853      * upper limit to this value appropriate to the numeric type being formatted.
854      * @see #getMaximumFractionDigits
855      */
setMaximumFractionDigits(int newValue)856     public void setMaximumFractionDigits(int newValue) {
857         maximumFractionDigits = Math.max(0,newValue);
858         if (maximumFractionDigits < minimumFractionDigits) {
859             minimumFractionDigits = maximumFractionDigits;
860         }
861     }
862 
863     /**
864      * Returns the minimum number of digits allowed in the fraction portion of a
865      * number.
866      *
867      * @return the minimum number of digits
868      * @see #setMinimumFractionDigits
869      */
getMinimumFractionDigits()870     public int getMinimumFractionDigits() {
871         return minimumFractionDigits;
872     }
873 
874     /**
875      * Sets the minimum number of digits allowed in the fraction portion of a
876      * number. minimumFractionDigits must be &le; maximumFractionDigits.  If the
877      * new value for minimumFractionDigits exceeds the current value
878      * of maximumFractionDigits, then maximumFractionDigits will also be set to
879      * the new value
880      *
881      * @param newValue the minimum number of fraction digits to be shown; if
882      * less than zero, then zero is used. The concrete subclass may enforce an
883      * upper limit to this value appropriate to the numeric type being formatted.
884      * @see #getMinimumFractionDigits
885      */
setMinimumFractionDigits(int newValue)886     public void setMinimumFractionDigits(int newValue) {
887         minimumFractionDigits = Math.max(0,newValue);
888         if (maximumFractionDigits < minimumFractionDigits) {
889             maximumFractionDigits = minimumFractionDigits;
890         }
891     }
892 
893     /**
894      * Gets the currency used by this number format when formatting
895      * currency values. The initial value is derived in a locale dependent
896      * way. The returned value may be null if no valid
897      * currency could be determined and no currency has been set using
898      * {@link #setCurrency(java.util.Currency) setCurrency}.
899      * <p>
900      * The default implementation throws
901      * {@code UnsupportedOperationException}.
902      *
903      * @return the currency used by this number format, or {@code null}
904      * @throws    UnsupportedOperationException if the number format class
905      * doesn't implement currency formatting
906      * @since 1.4
907      */
getCurrency()908     public Currency getCurrency() {
909         throw new UnsupportedOperationException();
910     }
911 
912     /**
913      * Sets the currency used by this number format when formatting
914      * currency values. This does not update the minimum or maximum
915      * number of fraction digits used by the number format.
916      * <p>
917      * The default implementation throws
918      * {@code UnsupportedOperationException}.
919      *
920      * @param currency the new currency to be used by this number format
921      * @throws    UnsupportedOperationException if the number format class
922      * doesn't implement currency formatting
923      * @throws    NullPointerException if {@code currency} is null
924      * @since 1.4
925      */
setCurrency(Currency currency)926     public void setCurrency(Currency currency) {
927         throw new UnsupportedOperationException();
928     }
929 
930     /**
931      * Gets the {@link java.math.RoundingMode} used in this NumberFormat.
932      * The default implementation of this method in NumberFormat
933      * always throws {@link java.lang.UnsupportedOperationException}.
934      * Subclasses which handle different rounding modes should override
935      * this method.
936      *
937      * @throws    UnsupportedOperationException The default implementation
938      *     always throws this exception
939      * @return The {@code RoundingMode} used for this NumberFormat.
940      * @see #setRoundingMode(RoundingMode)
941      * @since 1.6
942      */
getRoundingMode()943     public RoundingMode getRoundingMode() {
944         throw new UnsupportedOperationException();
945     }
946 
947     /**
948      * Sets the {@link java.math.RoundingMode} used in this NumberFormat.
949      * The default implementation of this method in NumberFormat always
950      * throws {@link java.lang.UnsupportedOperationException}.
951      * Subclasses which handle different rounding modes should override
952      * this method.
953      *
954      * @throws    UnsupportedOperationException The default implementation
955      *     always throws this exception
956      * @throws    NullPointerException if {@code roundingMode} is null
957      * @param roundingMode The {@code RoundingMode} to be used
958      * @see #getRoundingMode()
959      * @since 1.6
960      */
setRoundingMode(RoundingMode roundingMode)961     public void setRoundingMode(RoundingMode roundingMode) {
962         throw new UnsupportedOperationException();
963     }
964 
965     // =======================privates===============================
966 
getInstance(Locale desiredLocale, Style formatStyle, int choice)967     private static NumberFormat getInstance(Locale desiredLocale,
968                                             Style formatStyle, int choice) {
969         // BEGIN Android-changed: Removed use of NumberFormatProvider. Switched to use ICU.
970         /*
971         LocaleProviderAdapter adapter;
972         adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class,
973                 desiredLocale);
974         NumberFormat numberFormat = getInstance(adapter, desiredLocale,
975                 formatStyle, choice);
976         if (numberFormat == null) {
977             numberFormat = getInstance(LocaleProviderAdapter.forJRE(),
978                                        desiredLocale, choice);
979         */
980         String[] numberPatterns = new String[3];
981         DecimalFormatData data = DecimalFormatData.getInstance(desiredLocale);
982         numberPatterns[NUMBERSTYLE] = data.getNumberPattern();
983         numberPatterns[CURRENCYSTYLE] = data.getCurrencyPattern();
984         numberPatterns[PERCENTSTYLE] = data.getPercentPattern();
985 
986         // Note: the following lines are from NumberFormatProviderImpl upstream.
987         DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale);
988         int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
989         DecimalFormat numberFormat = new DecimalFormat(numberPatterns[entry], symbols);
990 
991         if (choice == INTEGERSTYLE) {
992             numberFormat.setMaximumFractionDigits(0);
993             numberFormat.setDecimalSeparatorAlwaysShown(false);
994             numberFormat.setParseIntegerOnly(true);
995         } else if (choice == CURRENCYSTYLE) {
996             numberFormat.adjustForCurrencyDefaultFractionDigits();
997         }
998         // END Android-changed: Removed use of NumberFormatProvider. Switched to use ICU.
999         return numberFormat;
1000     }
1001 
1002     // Android-removed: Removed use of LocaleProviderAdapter. Switched to use ICU.
1003     /*
1004     private static NumberFormat getInstance(LocaleProviderAdapter adapter,
1005                                             Locale locale, Style formatStyle,
1006                                             int choice) {
1007         NumberFormatProvider provider = adapter.getNumberFormatProvider();
1008         return switch (choice) {
1009             case NUMBERSTYLE   -> provider.getNumberInstance(locale);
1010             case PERCENTSTYLE  -> provider.getPercentInstance(locale);
1011             case CURRENCYSTYLE -> provider.getCurrencyInstance(locale);
1012             case INTEGERSTYLE  -> provider.getIntegerInstance(locale);
1013             case COMPACTSTYLE  -> provider.getCompactNumberInstance(locale, formatStyle);
1014             default            -> null;
1015         };
1016     }
1017     */
1018 
1019     /**
1020      * First, read in the default serializable data.
1021      *
1022      * Then, if {@code serialVersionOnStream} is less than 1, indicating that
1023      * the stream was written by JDK 1.1,
1024      * set the {@code int} fields such as {@code maximumIntegerDigits}
1025      * to be equal to the {@code byte} fields such as {@code maxIntegerDigits},
1026      * since the {@code int} fields were not present in JDK 1.1.
1027      * Finally, set serialVersionOnStream back to the maximum allowed value so that
1028      * default serialization will work properly if this object is streamed out again.
1029      *
1030      * <p>If {@code minimumIntegerDigits} is greater than
1031      * {@code maximumIntegerDigits} or {@code minimumFractionDigits}
1032      * is greater than {@code maximumFractionDigits}, then the stream data
1033      * is invalid and this method throws an {@code InvalidObjectException}.
1034      * In addition, if any of these values is negative, then this method throws
1035      * an {@code InvalidObjectException}.
1036      *
1037      * @since 1.2
1038      */
1039     @java.io.Serial
readObject(ObjectInputStream stream)1040     private void readObject(ObjectInputStream stream)
1041          throws IOException, ClassNotFoundException
1042     {
1043         stream.defaultReadObject();
1044         if (serialVersionOnStream < 1) {
1045             // Didn't have additional int fields, reassign to use them.
1046             maximumIntegerDigits = maxIntegerDigits;
1047             minimumIntegerDigits = minIntegerDigits;
1048             maximumFractionDigits = maxFractionDigits;
1049             minimumFractionDigits = minFractionDigits;
1050         }
1051         if (minimumIntegerDigits > maximumIntegerDigits ||
1052             minimumFractionDigits > maximumFractionDigits ||
1053             minimumIntegerDigits < 0 || minimumFractionDigits < 0) {
1054             throw new InvalidObjectException("Digit count range invalid");
1055         }
1056         serialVersionOnStream = currentSerialVersion;
1057     }
1058 
1059     /**
1060      * Write out the default serializable data, after first setting
1061      * the {@code byte} fields such as {@code maxIntegerDigits} to be
1062      * equal to the {@code int} fields such as {@code maximumIntegerDigits}
1063      * (or to {@code Byte.MAX_VALUE}, whichever is smaller), for compatibility
1064      * with the JDK 1.1 version of the stream format.
1065      *
1066      * @since 1.2
1067      */
1068     @java.io.Serial
writeObject(ObjectOutputStream stream)1069     private void writeObject(ObjectOutputStream stream)
1070          throws IOException
1071     {
1072         maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ?
1073                            Byte.MAX_VALUE : (byte)maximumIntegerDigits;
1074         minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ?
1075                            Byte.MAX_VALUE : (byte)minimumIntegerDigits;
1076         maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ?
1077                             Byte.MAX_VALUE : (byte)maximumFractionDigits;
1078         minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ?
1079                             Byte.MAX_VALUE : (byte)minimumFractionDigits;
1080         stream.defaultWriteObject();
1081     }
1082 
1083     // Constants used by factory methods to specify a style of format.
1084     private static final int NUMBERSTYLE = 0;
1085     private static final int CURRENCYSTYLE = 1;
1086     private static final int PERCENTSTYLE = 2;
1087     // Android-changed: Removed SCIENTIFICSTYLE and pull down INTEGERSTYLE value.
1088     //private static final int SCIENTIFICSTYLE = 3;
1089     private static final int INTEGERSTYLE = 3;
1090     // Android-removed: Removed unsupported COMPACTSTYLE.
1091     // private static final int COMPACTSTYLE = 5;
1092 
1093     /**
1094      * True if the grouping (i.e. thousands) separator is used when
1095      * formatting and parsing numbers.
1096      *
1097      * @serial
1098      * @see #isGroupingUsed
1099      */
1100     private boolean groupingUsed = true;
1101 
1102     /**
1103      * The maximum number of digits allowed in the integer portion of a
1104      * number.  {@code maxIntegerDigits} must be greater than or equal to
1105      * {@code minIntegerDigits}.
1106      * <p>
1107      * <strong>Note:</strong> This field exists only for serialization
1108      * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
1109      * {@code int} field {@code maximumIntegerDigits} is used instead.
1110      * When writing to a stream, {@code maxIntegerDigits} is set to
1111      * {@code maximumIntegerDigits} or {@code Byte.MAX_VALUE},
1112      * whichever is smaller.  When reading from a stream, this field is used
1113      * only if {@code serialVersionOnStream} is less than 1.
1114      *
1115      * @serial
1116      * @see #getMaximumIntegerDigits
1117      */
1118     private byte    maxIntegerDigits = 40;
1119 
1120     /**
1121      * The minimum number of digits allowed in the integer portion of a
1122      * number.  {@code minimumIntegerDigits} must be less than or equal to
1123      * {@code maximumIntegerDigits}.
1124      * <p>
1125      * <strong>Note:</strong> This field exists only for serialization
1126      * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
1127      * {@code int} field {@code minimumIntegerDigits} is used instead.
1128      * When writing to a stream, {@code minIntegerDigits} is set to
1129      * {@code minimumIntegerDigits} or {@code Byte.MAX_VALUE},
1130      * whichever is smaller.  When reading from a stream, this field is used
1131      * only if {@code serialVersionOnStream} is less than 1.
1132      *
1133      * @serial
1134      * @see #getMinimumIntegerDigits
1135      */
1136     private byte    minIntegerDigits = 1;
1137 
1138     /**
1139      * The maximum number of digits allowed in the fractional portion of a
1140      * number.  {@code maximumFractionDigits} must be greater than or equal to
1141      * {@code minimumFractionDigits}.
1142      * <p>
1143      * <strong>Note:</strong> This field exists only for serialization
1144      * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
1145      * {@code int} field {@code maximumFractionDigits} is used instead.
1146      * When writing to a stream, {@code maxFractionDigits} is set to
1147      * {@code maximumFractionDigits} or {@code Byte.MAX_VALUE},
1148      * whichever is smaller.  When reading from a stream, this field is used
1149      * only if {@code serialVersionOnStream} is less than 1.
1150      *
1151      * @serial
1152      * @see #getMaximumFractionDigits
1153      */
1154     private byte    maxFractionDigits = 3;    // invariant, >= minFractionDigits
1155 
1156     /**
1157      * The minimum number of digits allowed in the fractional portion of a
1158      * number.  {@code minimumFractionDigits} must be less than or equal to
1159      * {@code maximumFractionDigits}.
1160      * <p>
1161      * <strong>Note:</strong> This field exists only for serialization
1162      * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
1163      * {@code int} field {@code minimumFractionDigits} is used instead.
1164      * When writing to a stream, {@code minFractionDigits} is set to
1165      * {@code minimumFractionDigits} or {@code Byte.MAX_VALUE},
1166      * whichever is smaller.  When reading from a stream, this field is used
1167      * only if {@code serialVersionOnStream} is less than 1.
1168      *
1169      * @serial
1170      * @see #getMinimumFractionDigits
1171      */
1172     private byte    minFractionDigits = 0;
1173 
1174     /**
1175      * True if this format will parse numbers as integers only.
1176      *
1177      * @serial
1178      * @see #isParseIntegerOnly
1179      */
1180     private boolean parseIntegerOnly = false;
1181 
1182     // new fields for 1.2.  byte is too small for integer digits.
1183 
1184     /**
1185      * The maximum number of digits allowed in the integer portion of a
1186      * number.  {@code maximumIntegerDigits} must be greater than or equal to
1187      * {@code minimumIntegerDigits}.
1188      *
1189      * @serial
1190      * @since 1.2
1191      * @see #getMaximumIntegerDigits
1192      */
1193     private int    maximumIntegerDigits = 40;
1194 
1195     /**
1196      * The minimum number of digits allowed in the integer portion of a
1197      * number.  {@code minimumIntegerDigits} must be less than or equal to
1198      * {@code maximumIntegerDigits}.
1199      *
1200      * @serial
1201      * @since 1.2
1202      * @see #getMinimumIntegerDigits
1203      */
1204     private int    minimumIntegerDigits = 1;
1205 
1206     /**
1207      * The maximum number of digits allowed in the fractional portion of a
1208      * number.  {@code maximumFractionDigits} must be greater than or equal to
1209      * {@code minimumFractionDigits}.
1210      *
1211      * @serial
1212      * @since 1.2
1213      * @see #getMaximumFractionDigits
1214      */
1215     private int    maximumFractionDigits = 3;    // invariant, >= minFractionDigits
1216 
1217     /**
1218      * The minimum number of digits allowed in the fractional portion of a
1219      * number.  {@code minimumFractionDigits} must be less than or equal to
1220      * {@code maximumFractionDigits}.
1221      *
1222      * @serial
1223      * @since 1.2
1224      * @see #getMinimumFractionDigits
1225      */
1226     private int    minimumFractionDigits = 0;
1227 
1228     static final int currentSerialVersion = 1;
1229 
1230     /**
1231      * Describes the version of {@code NumberFormat} present on the stream.
1232      * Possible values are:
1233      * <ul>
1234      * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format.
1235      *     In this version, the {@code int} fields such as
1236      *     {@code maximumIntegerDigits} were not present, and the {@code byte}
1237      *     fields such as {@code maxIntegerDigits} are used instead.
1238      *
1239      * <li><b>1</b>: the 1.2 version of the stream format.  The values of the
1240      *     {@code byte} fields such as {@code maxIntegerDigits} are ignored,
1241      *     and the {@code int} fields such as {@code maximumIntegerDigits}
1242      *     are used instead.
1243      * </ul>
1244      * When streaming out a {@code NumberFormat}, the most recent format
1245      * (corresponding to the highest allowable {@code serialVersionOnStream})
1246      * is always written.
1247      *
1248      * @serial
1249      * @since 1.2
1250      */
1251     private int serialVersionOnStream = currentSerialVersion;
1252 
1253     // Removed "implements Cloneable" clause.  Needs to update serialization
1254     // ID for backward compatibility.
1255     @java.io.Serial
1256     static final long serialVersionUID = -2308460125733713944L;
1257 
1258 
1259     //
1260     // class for AttributedCharacterIterator attributes
1261     //
1262     /**
1263      * Defines constants that are used as attribute keys in the
1264      * {@code AttributedCharacterIterator} returned
1265      * from {@code NumberFormat.formatToCharacterIterator} and as
1266      * field identifiers in {@code FieldPosition}.
1267      *
1268      * @since 1.4
1269      */
1270     public static class Field extends Format.Field {
1271 
1272         // Proclaim serial compatibility with 1.4 FCS
1273         @java.io.Serial
1274         private static final long serialVersionUID = 7494728892700160890L;
1275 
1276         // table of all instances in this class, used by readResolve
1277         private static final Map<String, Field> instanceMap = new HashMap<>(11);
1278 
1279         /**
1280          * Creates a Field instance with the specified
1281          * name.
1282          *
1283          * @param name Name of the attribute
1284          */
Field(String name)1285         protected Field(String name) {
1286             super(name);
1287             if (this.getClass() == NumberFormat.Field.class) {
1288                 instanceMap.put(name, this);
1289             }
1290         }
1291 
1292         /**
1293          * Resolves instances being deserialized to the predefined constants.
1294          *
1295          * @throws InvalidObjectException if the constant could not be resolved.
1296          * @return resolved NumberFormat.Field constant
1297          */
1298         @Override
1299         @java.io.Serial
readResolve()1300         protected Object readResolve() throws InvalidObjectException {
1301             if (this.getClass() != NumberFormat.Field.class) {
1302                 throw new InvalidObjectException("subclass didn't correctly implement readResolve");
1303             }
1304 
1305             Object instance = instanceMap.get(getName());
1306             if (instance != null) {
1307                 return instance;
1308             } else {
1309                 throw new InvalidObjectException("unknown attribute name");
1310             }
1311         }
1312 
1313         /**
1314          * Constant identifying the integer field.
1315          */
1316         public static final Field INTEGER = new Field("integer");
1317 
1318         /**
1319          * Constant identifying the fraction field.
1320          */
1321         public static final Field FRACTION = new Field("fraction");
1322 
1323         /**
1324          * Constant identifying the exponent field.
1325          */
1326         public static final Field EXPONENT = new Field("exponent");
1327 
1328         /**
1329          * Constant identifying the decimal separator field.
1330          */
1331         public static final Field DECIMAL_SEPARATOR =
1332                             new Field("decimal separator");
1333 
1334         /**
1335          * Constant identifying the sign field.
1336          */
1337         public static final Field SIGN = new Field("sign");
1338 
1339         /**
1340          * Constant identifying the grouping separator field.
1341          */
1342         public static final Field GROUPING_SEPARATOR =
1343                             new Field("grouping separator");
1344 
1345         /**
1346          * Constant identifying the exponent symbol field.
1347          */
1348         public static final Field EXPONENT_SYMBOL = new
1349                             Field("exponent symbol");
1350 
1351         /**
1352          * Constant identifying the percent field.
1353          */
1354         public static final Field PERCENT = new Field("percent");
1355 
1356         /**
1357          * Constant identifying the permille field.
1358          */
1359         public static final Field PERMILLE = new Field("per mille");
1360 
1361         /**
1362          * Constant identifying the currency field.
1363          */
1364         public static final Field CURRENCY = new Field("currency");
1365 
1366         /**
1367          * Constant identifying the exponent sign field.
1368          */
1369         public static final Field EXPONENT_SIGN = new Field("exponent sign");
1370 
1371         // Android-changed: Hide PREFIX field not supported by ICU.
1372         /**
1373          * Constant identifying the prefix field.
1374          *
1375          * @since 12
1376          * @hide
1377          */
1378         public static final Field PREFIX = new Field("prefix");
1379 
1380         // Android-changed: Hide SUFFIX field not supported by ICU.
1381         /**
1382          * Constant identifying the suffix field.
1383          *
1384          * @since 12
1385          * @hide
1386          */
1387         public static final Field SUFFIX = new Field("suffix");
1388     }
1389 
1390 
1391     // Android-changed: Make unsupported Style private and removed the enum values.
1392     /**
1393      * A number format style.
1394      * <p>
1395      * {@code Style} is an enum which represents the style for formatting
1396      * a number within a given {@code NumberFormat} instance.
1397      * @since 12
1398      */
1399     private enum Style {
1400 
1401        /**
1402          * The {@code SHORT} number format style.
1403          *//*
1404         SHORT,
1405 
1406         *//**
1407          * The {@code LONG} number format style.
1408          *//*
1409         LONG
1410         */
1411 
1412     }
1413 }
1414