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" → 3456 (and leaves the parse position just after index 6) 141 * if false, "3456.78" → 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 → "3,456." 150 * if false, 3456.00 → "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 ≥ 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 ≤ 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 ≥ 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 ≤ 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