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 /** 396 * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE, 397 * Long.MAX_VALUE] and with no decimals), otherwise a Double. 398 * If IntegerOnly is set, will stop at a decimal 399 * point (or equivalent; e.g., for rational numbers "1 2/3", will stop 400 * after the 1). 401 * Does not throw an exception; if no object can be parsed, index is 402 * unchanged! 403 * 404 * @param source the String to parse 405 * @param parsePosition the parse position 406 * @return the parsed value 407 * @see java.text.NumberFormat#isParseIntegerOnly 408 * @see java.text.Format#parseObject 409 */ parse(String source, ParsePosition parsePosition)410 public abstract Number parse(String source, ParsePosition parsePosition); 411 412 /** 413 * Parses text from the beginning of the given string to produce a number. 414 * The method may not use the entire text of the given string. 415 * <p> 416 * See the {@link #parse(String, ParsePosition)} method for more information 417 * on number parsing. 418 * 419 * @param source A {@code String} whose beginning should be parsed. 420 * @return A {@code Number} parsed from the string. 421 * @throws ParseException if the beginning of the specified string 422 * cannot be parsed. 423 */ parse(String source)424 public Number parse(String source) throws ParseException { 425 ParsePosition parsePosition = new ParsePosition(0); 426 Number result = parse(source, parsePosition); 427 if (parsePosition.index == 0) { 428 throw new ParseException("Unparseable number: \"" + source + "\"", 429 parsePosition.errorIndex); 430 } 431 return result; 432 } 433 434 /** 435 * Returns true if this format will parse numbers as integers only. 436 * For example in the English locale, with ParseIntegerOnly true, the 437 * string "1234." would be parsed as the integer value 1234 and parsing 438 * would stop at the "." character. Of course, the exact format accepted 439 * by the parse operation is locale dependent and determined by sub-classes 440 * of NumberFormat. 441 * 442 * @return {@code true} if numbers should be parsed as integers only; 443 * {@code false} otherwise 444 */ isParseIntegerOnly()445 public boolean isParseIntegerOnly() { 446 return parseIntegerOnly; 447 } 448 449 /** 450 * Sets whether or not numbers should be parsed as integers only. 451 * 452 * @param value {@code true} if numbers should be parsed as integers only; 453 * {@code false} otherwise 454 * @see #isParseIntegerOnly 455 */ setParseIntegerOnly(boolean value)456 public void setParseIntegerOnly(boolean value) { 457 parseIntegerOnly = value; 458 } 459 460 //============== Locale Stuff ===================== 461 462 /** 463 * Returns a general-purpose number format for the current default 464 * {@link java.util.Locale.Category#FORMAT FORMAT} locale. 465 * This is the same as calling 466 * {@link #getNumberInstance() getNumberInstance()}. 467 * 468 * @return the {@code NumberFormat} instance for general-purpose number 469 * formatting 470 */ getInstance()471 public static final NumberFormat getInstance() { 472 return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, NUMBERSTYLE); 473 } 474 475 /** 476 * Returns a general-purpose number format for the specified locale. 477 * This is the same as calling 478 * {@link #getNumberInstance(java.util.Locale) getNumberInstance(inLocale)}. 479 * 480 * @param inLocale the desired locale 481 * @return the {@code NumberFormat} instance for general-purpose number 482 * formatting 483 */ getInstance(Locale inLocale)484 public static NumberFormat getInstance(Locale inLocale) { 485 return getInstance(inLocale, null, NUMBERSTYLE); 486 } 487 488 /** 489 * Returns a general-purpose number format for the current default 490 * {@link java.util.Locale.Category#FORMAT FORMAT} locale. 491 * <p>This is equivalent to calling 492 * {@link #getNumberInstance(Locale) 493 * getNumberInstance(Locale.getDefault(Locale.Category.FORMAT))}. 494 * 495 * @return the {@code NumberFormat} instance for general-purpose number 496 * formatting 497 * @see java.util.Locale#getDefault(java.util.Locale.Category) 498 * @see java.util.Locale.Category#FORMAT 499 */ getNumberInstance()500 public static final NumberFormat getNumberInstance() { 501 return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, NUMBERSTYLE); 502 } 503 504 /** 505 * Returns a general-purpose number format for the specified locale. 506 * 507 * @param inLocale the desired locale 508 * @return the {@code NumberFormat} instance for general-purpose number 509 * formatting 510 */ getNumberInstance(Locale inLocale)511 public static NumberFormat getNumberInstance(Locale inLocale) { 512 return getInstance(inLocale, null, NUMBERSTYLE); 513 } 514 515 /** 516 * Returns an integer number format for the current default 517 * {@link java.util.Locale.Category#FORMAT FORMAT} locale. The 518 * returned number format is configured to round floating point numbers 519 * to the nearest integer using half-even rounding (see {@link 520 * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting, 521 * and to parse only the integer part of an input string (see {@link 522 * #isParseIntegerOnly isParseIntegerOnly}). 523 * <p>This is equivalent to calling 524 * {@link #getIntegerInstance(Locale) 525 * getIntegerInstance(Locale.getDefault(Locale.Category.FORMAT))}. 526 * 527 * @see #getRoundingMode() 528 * @see java.util.Locale#getDefault(java.util.Locale.Category) 529 * @see java.util.Locale.Category#FORMAT 530 * @return a number format for integer values 531 * @since 1.4 532 */ getIntegerInstance()533 public static final NumberFormat getIntegerInstance() { 534 return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, INTEGERSTYLE); 535 } 536 537 /** 538 * Returns an integer number format for the specified locale. The 539 * returned number format is configured to round floating point numbers 540 * to the nearest integer using half-even rounding (see {@link 541 * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting, 542 * and to parse only the integer part of an input string (see {@link 543 * #isParseIntegerOnly isParseIntegerOnly}). 544 * 545 * @param inLocale the desired locale 546 * @see #getRoundingMode() 547 * @return a number format for integer values 548 * @since 1.4 549 */ getIntegerInstance(Locale inLocale)550 public static NumberFormat getIntegerInstance(Locale inLocale) { 551 return getInstance(inLocale, null, INTEGERSTYLE); 552 } 553 554 /** 555 * Returns a currency format for the current default 556 * {@link java.util.Locale.Category#FORMAT FORMAT} locale. 557 * <p>This is equivalent to calling 558 * {@link #getCurrencyInstance(Locale) 559 * getCurrencyInstance(Locale.getDefault(Locale.Category.FORMAT))}. 560 * 561 * @return the {@code NumberFormat} instance for currency formatting 562 * @see java.util.Locale#getDefault(java.util.Locale.Category) 563 * @see java.util.Locale.Category#FORMAT 564 */ getCurrencyInstance()565 public static final NumberFormat getCurrencyInstance() { 566 return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, CURRENCYSTYLE); 567 } 568 569 /** 570 * Returns a currency format for the specified locale. 571 * 572 * <p>If the specified locale contains the "{@code cf}" ( 573 * <a href="https://www.unicode.org/reports/tr35/tr35.html#UnicodeCurrencyFormatIdentifier"> 574 * currency format style</a>) 575 * <a href="../util/Locale.html#def_locale_extension">Unicode extension</a>, 576 * the returned currency format uses the style if it is available. 577 * Otherwise, the style uses the default "{@code standard}" currency format. 578 * For example, if the style designates "{@code account}", negative 579 * currency amounts use a pair of parentheses in some locales. 580 * 581 * @param inLocale the desired locale 582 * @return the {@code NumberFormat} instance for currency formatting 583 */ getCurrencyInstance(Locale inLocale)584 public static NumberFormat getCurrencyInstance(Locale inLocale) { 585 return getInstance(inLocale, null, CURRENCYSTYLE); 586 } 587 588 /** 589 * Returns a percentage format for the current default 590 * {@link java.util.Locale.Category#FORMAT FORMAT} locale. 591 * <p>This is equivalent to calling 592 * {@link #getPercentInstance(Locale) 593 * getPercentInstance(Locale.getDefault(Locale.Category.FORMAT))}. 594 * 595 * @return the {@code NumberFormat} instance for percentage formatting 596 * @see java.util.Locale#getDefault(java.util.Locale.Category) 597 * @see java.util.Locale.Category#FORMAT 598 */ getPercentInstance()599 public static final NumberFormat getPercentInstance() { 600 return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, PERCENTSTYLE); 601 } 602 603 /** 604 * Returns a percentage format for the specified locale. 605 * 606 * @param inLocale the desired locale 607 * @return the {@code NumberFormat} instance for percentage formatting 608 */ getPercentInstance(Locale inLocale)609 public static NumberFormat getPercentInstance(Locale inLocale) { 610 return getInstance(inLocale, null, PERCENTSTYLE); 611 } 612 613 // BEGIN Android-removed: non-API methods getScientificInstance([Locale]). 614 /** 615 * Returns a scientific format for the current default locale. 616 * 617 /*public* static final NumberFormat getScientificInstance() { 618 return getInstance(Locale.getDefault(Locale.Category.FORMAT), null, SCIENTIFICSTYLE); 619 } 620 621 /** 622 * Returns a scientific format for the specified locale. 623 * 624 * @param inLocale the desired locale 625 * 626 /*public* static NumberFormat getScientificInstance(Locale inLocale) { 627 return getInstance(inLocale, null, SCIENTIFICSTYLE); 628 } 629 */ 630 // END Android-removed: non-API methods getScientificInstance([Locale]). 631 632 // BEGIN Android-removed: Remove unsupported CompactNumberFormat. 633 /* 634 * Returns a compact number format for the default 635 * {@link java.util.Locale.Category#FORMAT FORMAT} locale with 636 * {@link NumberFormat.Style#SHORT "SHORT"} format style. 637 * 638 * @return A {@code NumberFormat} instance for compact number 639 * formatting 640 * 641 * @see CompactNumberFormat 642 * @see NumberFormat.Style 643 * @see java.util.Locale#getDefault(java.util.Locale.Category) 644 * @see java.util.Locale.Category#FORMAT 645 * @since 12 646 * 647 public static NumberFormat getCompactNumberInstance() { 648 return getInstance(Locale.getDefault( 649 Locale.Category.FORMAT), NumberFormat.Style.SHORT, COMPACTSTYLE); 650 } 651 652 /* 653 * Returns a compact number format for the specified {@link java.util.Locale locale} 654 * and {@link NumberFormat.Style formatStyle}. 655 * 656 * @param locale the desired locale 657 * @param formatStyle the style for formatting a number 658 * @return A {@code NumberFormat} instance for compact number 659 * formatting 660 * @throws NullPointerException if {@code locale} or {@code formatStyle} 661 * is {@code null} 662 * 663 * @see CompactNumberFormat 664 * @see NumberFormat.Style 665 * @see java.util.Locale 666 * @since 12 667 * 668 public static NumberFormat getCompactNumberInstance(Locale locale, 669 NumberFormat.Style formatStyle) { 670 671 Objects.requireNonNull(locale); 672 Objects.requireNonNull(formatStyle); 673 return getInstance(locale, formatStyle, COMPACTSTYLE); 674 } 675 // END Android-removed: Remove unsupprted CompactNumberFormat. 676 677 // Android-changed: Removed reference to NumberFormatProvider. 678 /** 679 * Returns an array of all locales for which the 680 * {@code get*Instance} methods of this class can return 681 * localized instances. 682 * It must contain at least a {@code Locale} instance equal to 683 * {@link java.util.Locale#US Locale.US}. 684 * 685 * @return An array of locales for which localized 686 * {@code NumberFormat} instances are available. 687 */ getAvailableLocales()688 public static Locale[] getAvailableLocales() { 689 // Android-changed: Removed used of NumberFormatProvider. Switched to use ICU. 690 return ICU.getAvailableLocales(); 691 } 692 693 /** 694 * Overrides hashCode. 695 */ 696 @Override hashCode()697 public int hashCode() { 698 return maximumIntegerDigits * 37 + maxFractionDigits; 699 // just enough fields for a reasonable distribution 700 } 701 702 /** 703 * Overrides equals. 704 */ 705 @Override equals(Object obj)706 public boolean equals(Object obj) { 707 if (obj == null) { 708 return false; 709 } 710 if (this == obj) { 711 return true; 712 } 713 if (getClass() != obj.getClass()) { 714 return false; 715 } 716 NumberFormat other = (NumberFormat) obj; 717 return (maximumIntegerDigits == other.maximumIntegerDigits 718 && minimumIntegerDigits == other.minimumIntegerDigits 719 && maximumFractionDigits == other.maximumFractionDigits 720 && minimumFractionDigits == other.minimumFractionDigits 721 && groupingUsed == other.groupingUsed 722 && parseIntegerOnly == other.parseIntegerOnly); 723 } 724 725 /** 726 * Overrides Cloneable. 727 */ 728 @Override clone()729 public Object clone() { 730 NumberFormat other = (NumberFormat) super.clone(); 731 return other; 732 } 733 734 /** 735 * Returns true if grouping is used in this format. For example, in the 736 * English locale, with grouping on, the number 1234567 might be formatted 737 * as "1,234,567". The grouping separator as well as the size of each group 738 * is locale dependent and is determined by sub-classes of NumberFormat. 739 * 740 * @return {@code true} if grouping is used; 741 * {@code false} otherwise 742 * @see #setGroupingUsed 743 */ isGroupingUsed()744 public boolean isGroupingUsed() { 745 return groupingUsed; 746 } 747 748 /** 749 * Set whether or not grouping will be used in this format. 750 * 751 * @param newValue {@code true} if grouping is used; 752 * {@code false} otherwise 753 * @see #isGroupingUsed 754 */ setGroupingUsed(boolean newValue)755 public void setGroupingUsed(boolean newValue) { 756 groupingUsed = newValue; 757 } 758 759 /** 760 * Returns the maximum number of digits allowed in the integer portion of a 761 * number. 762 * 763 * @return the maximum number of digits 764 * @see #setMaximumIntegerDigits 765 */ getMaximumIntegerDigits()766 public int getMaximumIntegerDigits() { 767 return maximumIntegerDigits; 768 } 769 770 /** 771 * Sets the maximum number of digits allowed in the integer portion of a 772 * number. maximumIntegerDigits must be ≥ minimumIntegerDigits. If the 773 * new value for maximumIntegerDigits is less than the current value 774 * of minimumIntegerDigits, then minimumIntegerDigits will also be set to 775 * the new value. 776 * 777 * @param newValue the maximum number of integer digits to be shown; if 778 * less than zero, then zero is used. The concrete subclass may enforce an 779 * upper limit to this value appropriate to the numeric type being formatted. 780 * @see #getMaximumIntegerDigits 781 */ setMaximumIntegerDigits(int newValue)782 public void setMaximumIntegerDigits(int newValue) { 783 maximumIntegerDigits = Math.max(0,newValue); 784 if (minimumIntegerDigits > maximumIntegerDigits) { 785 minimumIntegerDigits = maximumIntegerDigits; 786 } 787 } 788 789 /** 790 * Returns the minimum number of digits allowed in the integer portion of a 791 * number. 792 * 793 * @return the minimum number of digits 794 * @see #setMinimumIntegerDigits 795 */ getMinimumIntegerDigits()796 public int getMinimumIntegerDigits() { 797 return minimumIntegerDigits; 798 } 799 800 /** 801 * Sets the minimum number of digits allowed in the integer portion of a 802 * number. minimumIntegerDigits must be ≤ maximumIntegerDigits. If the 803 * new value for minimumIntegerDigits exceeds the current value 804 * of maximumIntegerDigits, then maximumIntegerDigits will also be set to 805 * the new value 806 * 807 * @param newValue the minimum number of integer digits to be shown; if 808 * less than zero, then zero is used. The concrete subclass may enforce an 809 * upper limit to this value appropriate to the numeric type being formatted. 810 * @see #getMinimumIntegerDigits 811 */ setMinimumIntegerDigits(int newValue)812 public void setMinimumIntegerDigits(int newValue) { 813 minimumIntegerDigits = Math.max(0,newValue); 814 if (minimumIntegerDigits > maximumIntegerDigits) { 815 maximumIntegerDigits = minimumIntegerDigits; 816 } 817 } 818 819 /** 820 * Returns the maximum number of digits allowed in the fraction portion of a 821 * number. 822 * 823 * @return the maximum number of digits. 824 * @see #setMaximumFractionDigits 825 */ getMaximumFractionDigits()826 public int getMaximumFractionDigits() { 827 return maximumFractionDigits; 828 } 829 830 /** 831 * Sets the maximum number of digits allowed in the fraction portion of a 832 * number. maximumFractionDigits must be ≥ minimumFractionDigits. If the 833 * new value for maximumFractionDigits is less than the current value 834 * of minimumFractionDigits, then minimumFractionDigits will also be set to 835 * the new value. 836 * 837 * @param newValue the maximum number of fraction digits to be shown; if 838 * less than zero, then zero is used. The concrete subclass may enforce an 839 * upper limit to this value appropriate to the numeric type being formatted. 840 * @see #getMaximumFractionDigits 841 */ setMaximumFractionDigits(int newValue)842 public void setMaximumFractionDigits(int newValue) { 843 maximumFractionDigits = Math.max(0,newValue); 844 if (maximumFractionDigits < minimumFractionDigits) { 845 minimumFractionDigits = maximumFractionDigits; 846 } 847 } 848 849 /** 850 * Returns the minimum number of digits allowed in the fraction portion of a 851 * number. 852 * 853 * @return the minimum number of digits 854 * @see #setMinimumFractionDigits 855 */ getMinimumFractionDigits()856 public int getMinimumFractionDigits() { 857 return minimumFractionDigits; 858 } 859 860 /** 861 * Sets the minimum number of digits allowed in the fraction portion of a 862 * number. minimumFractionDigits must be ≤ maximumFractionDigits. If the 863 * new value for minimumFractionDigits exceeds the current value 864 * of maximumFractionDigits, then maximumFractionDigits will also be set to 865 * the new value 866 * 867 * @param newValue the minimum number of fraction digits to be shown; if 868 * less than zero, then zero is used. The concrete subclass may enforce an 869 * upper limit to this value appropriate to the numeric type being formatted. 870 * @see #getMinimumFractionDigits 871 */ setMinimumFractionDigits(int newValue)872 public void setMinimumFractionDigits(int newValue) { 873 minimumFractionDigits = Math.max(0,newValue); 874 if (maximumFractionDigits < minimumFractionDigits) { 875 maximumFractionDigits = minimumFractionDigits; 876 } 877 } 878 879 /** 880 * Gets the currency used by this number format when formatting 881 * currency values. The initial value is derived in a locale dependent 882 * way. The returned value may be null if no valid 883 * currency could be determined and no currency has been set using 884 * {@link #setCurrency(java.util.Currency) setCurrency}. 885 * <p> 886 * The default implementation throws 887 * {@code UnsupportedOperationException}. 888 * 889 * @return the currency used by this number format, or {@code null} 890 * @throws UnsupportedOperationException if the number format class 891 * doesn't implement currency formatting 892 * @since 1.4 893 */ getCurrency()894 public Currency getCurrency() { 895 throw new UnsupportedOperationException(); 896 } 897 898 /** 899 * Sets the currency used by this number format when formatting 900 * currency values. This does not update the minimum or maximum 901 * number of fraction digits used by the number format. 902 * <p> 903 * The default implementation throws 904 * {@code UnsupportedOperationException}. 905 * 906 * @param currency the new currency to be used by this number format 907 * @throws UnsupportedOperationException if the number format class 908 * doesn't implement currency formatting 909 * @throws NullPointerException if {@code currency} is null 910 * @since 1.4 911 */ setCurrency(Currency currency)912 public void setCurrency(Currency currency) { 913 throw new UnsupportedOperationException(); 914 } 915 916 /** 917 * Gets the {@link java.math.RoundingMode} used in this NumberFormat. 918 * The default implementation of this method in NumberFormat 919 * always throws {@link java.lang.UnsupportedOperationException}. 920 * Subclasses which handle different rounding modes should override 921 * this method. 922 * 923 * @throws UnsupportedOperationException The default implementation 924 * always throws this exception 925 * @return The {@code RoundingMode} used for this NumberFormat. 926 * @see #setRoundingMode(RoundingMode) 927 * @since 1.6 928 */ getRoundingMode()929 public RoundingMode getRoundingMode() { 930 throw new UnsupportedOperationException(); 931 } 932 933 /** 934 * Sets the {@link java.math.RoundingMode} used in this NumberFormat. 935 * The default implementation of this method in NumberFormat always 936 * throws {@link java.lang.UnsupportedOperationException}. 937 * Subclasses which handle different rounding modes should override 938 * this method. 939 * 940 * @throws UnsupportedOperationException The default implementation 941 * always throws this exception 942 * @throws NullPointerException if {@code roundingMode} is null 943 * @param roundingMode The {@code RoundingMode} to be used 944 * @see #getRoundingMode() 945 * @since 1.6 946 */ setRoundingMode(RoundingMode roundingMode)947 public void setRoundingMode(RoundingMode roundingMode) { 948 throw new UnsupportedOperationException(); 949 } 950 951 // =======================privates=============================== 952 getInstance(Locale desiredLocale, Style formatStyle, int choice)953 private static NumberFormat getInstance(Locale desiredLocale, 954 Style formatStyle, int choice) { 955 // BEGIN Android-changed: Removed use of NumberFormatProvider. Switched to use ICU. 956 /* 957 LocaleProviderAdapter adapter; 958 adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, 959 desiredLocale); 960 NumberFormat numberFormat = getInstance(adapter, desiredLocale, 961 formatStyle, choice); 962 if (numberFormat == null) { 963 numberFormat = getInstance(LocaleProviderAdapter.forJRE(), 964 desiredLocale, choice); 965 */ 966 String[] numberPatterns = new String[3]; 967 DecimalFormatData data = DecimalFormatData.getInstance(desiredLocale); 968 numberPatterns[NUMBERSTYLE] = data.getNumberPattern(); 969 numberPatterns[CURRENCYSTYLE] = data.getCurrencyPattern(); 970 numberPatterns[PERCENTSTYLE] = data.getPercentPattern(); 971 972 // Note: the following lines are from NumberFormatProviderImpl upstream. 973 DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale); 974 int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice; 975 DecimalFormat numberFormat = new DecimalFormat(numberPatterns[entry], symbols); 976 977 if (choice == INTEGERSTYLE) { 978 numberFormat.setMaximumFractionDigits(0); 979 numberFormat.setDecimalSeparatorAlwaysShown(false); 980 numberFormat.setParseIntegerOnly(true); 981 } else if (choice == CURRENCYSTYLE) { 982 numberFormat.adjustForCurrencyDefaultFractionDigits(); 983 } 984 // END Android-changed: Removed use of NumberFormatProvider. Switched to use ICU. 985 return numberFormat; 986 } 987 988 // Android-removed: Removed use of LocaleProviderAdapter. Switched to use ICU. 989 /* 990 private static NumberFormat getInstance(LocaleProviderAdapter adapter, 991 Locale locale, Style formatStyle, 992 int choice) { 993 NumberFormatProvider provider = adapter.getNumberFormatProvider(); 994 return switch (choice) { 995 case NUMBERSTYLE -> provider.getNumberInstance(locale); 996 case PERCENTSTYLE -> provider.getPercentInstance(locale); 997 case CURRENCYSTYLE -> provider.getCurrencyInstance(locale); 998 case INTEGERSTYLE -> provider.getIntegerInstance(locale); 999 case COMPACTSTYLE -> provider.getCompactNumberInstance(locale, formatStyle); 1000 default -> null; 1001 }; 1002 } 1003 */ 1004 1005 /** 1006 * First, read in the default serializable data. 1007 * 1008 * Then, if {@code serialVersionOnStream} is less than 1, indicating that 1009 * the stream was written by JDK 1.1, 1010 * set the {@code int} fields such as {@code maximumIntegerDigits} 1011 * to be equal to the {@code byte} fields such as {@code maxIntegerDigits}, 1012 * since the {@code int} fields were not present in JDK 1.1. 1013 * Finally, set serialVersionOnStream back to the maximum allowed value so that 1014 * default serialization will work properly if this object is streamed out again. 1015 * 1016 * <p>If {@code minimumIntegerDigits} is greater than 1017 * {@code maximumIntegerDigits} or {@code minimumFractionDigits} 1018 * is greater than {@code maximumFractionDigits}, then the stream data 1019 * is invalid and this method throws an {@code InvalidObjectException}. 1020 * In addition, if any of these values is negative, then this method throws 1021 * an {@code InvalidObjectException}. 1022 * 1023 * @since 1.2 1024 */ 1025 @java.io.Serial readObject(ObjectInputStream stream)1026 private void readObject(ObjectInputStream stream) 1027 throws IOException, ClassNotFoundException 1028 { 1029 stream.defaultReadObject(); 1030 if (serialVersionOnStream < 1) { 1031 // Didn't have additional int fields, reassign to use them. 1032 maximumIntegerDigits = maxIntegerDigits; 1033 minimumIntegerDigits = minIntegerDigits; 1034 maximumFractionDigits = maxFractionDigits; 1035 minimumFractionDigits = minFractionDigits; 1036 } 1037 if (minimumIntegerDigits > maximumIntegerDigits || 1038 minimumFractionDigits > maximumFractionDigits || 1039 minimumIntegerDigits < 0 || minimumFractionDigits < 0) { 1040 throw new InvalidObjectException("Digit count range invalid"); 1041 } 1042 serialVersionOnStream = currentSerialVersion; 1043 } 1044 1045 /** 1046 * Write out the default serializable data, after first setting 1047 * the {@code byte} fields such as {@code maxIntegerDigits} to be 1048 * equal to the {@code int} fields such as {@code maximumIntegerDigits} 1049 * (or to {@code Byte.MAX_VALUE}, whichever is smaller), for compatibility 1050 * with the JDK 1.1 version of the stream format. 1051 * 1052 * @since 1.2 1053 */ 1054 @java.io.Serial writeObject(ObjectOutputStream stream)1055 private void writeObject(ObjectOutputStream stream) 1056 throws IOException 1057 { 1058 maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ? 1059 Byte.MAX_VALUE : (byte)maximumIntegerDigits; 1060 minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ? 1061 Byte.MAX_VALUE : (byte)minimumIntegerDigits; 1062 maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ? 1063 Byte.MAX_VALUE : (byte)maximumFractionDigits; 1064 minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ? 1065 Byte.MAX_VALUE : (byte)minimumFractionDigits; 1066 stream.defaultWriteObject(); 1067 } 1068 1069 // Constants used by factory methods to specify a style of format. 1070 private static final int NUMBERSTYLE = 0; 1071 private static final int CURRENCYSTYLE = 1; 1072 private static final int PERCENTSTYLE = 2; 1073 // Android-changed: Removed SCIENTIFICSTYLE and pull down INTEGERSTYLE value. 1074 //private static final int SCIENTIFICSTYLE = 3; 1075 private static final int INTEGERSTYLE = 3; 1076 // Android-removed: Removed unsupported COMPACTSTYLE. 1077 // private static final int COMPACTSTYLE = 5; 1078 1079 /** 1080 * True if the grouping (i.e. thousands) separator is used when 1081 * formatting and parsing numbers. 1082 * 1083 * @serial 1084 * @see #isGroupingUsed 1085 */ 1086 private boolean groupingUsed = true; 1087 1088 /** 1089 * The maximum number of digits allowed in the integer portion of a 1090 * number. {@code maxIntegerDigits} must be greater than or equal to 1091 * {@code minIntegerDigits}. 1092 * <p> 1093 * <strong>Note:</strong> This field exists only for serialization 1094 * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 1095 * {@code int} field {@code maximumIntegerDigits} is used instead. 1096 * When writing to a stream, {@code maxIntegerDigits} is set to 1097 * {@code maximumIntegerDigits} or {@code Byte.MAX_VALUE}, 1098 * whichever is smaller. When reading from a stream, this field is used 1099 * only if {@code serialVersionOnStream} is less than 1. 1100 * 1101 * @serial 1102 * @see #getMaximumIntegerDigits 1103 */ 1104 private byte maxIntegerDigits = 40; 1105 1106 /** 1107 * The minimum number of digits allowed in the integer portion of a 1108 * number. {@code minimumIntegerDigits} must be less than or equal to 1109 * {@code maximumIntegerDigits}. 1110 * <p> 1111 * <strong>Note:</strong> This field exists only for serialization 1112 * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 1113 * {@code int} field {@code minimumIntegerDigits} is used instead. 1114 * When writing to a stream, {@code minIntegerDigits} is set to 1115 * {@code minimumIntegerDigits} or {@code Byte.MAX_VALUE}, 1116 * whichever is smaller. When reading from a stream, this field is used 1117 * only if {@code serialVersionOnStream} is less than 1. 1118 * 1119 * @serial 1120 * @see #getMinimumIntegerDigits 1121 */ 1122 private byte minIntegerDigits = 1; 1123 1124 /** 1125 * The maximum number of digits allowed in the fractional portion of a 1126 * number. {@code maximumFractionDigits} must be greater than or equal to 1127 * {@code minimumFractionDigits}. 1128 * <p> 1129 * <strong>Note:</strong> This field exists only for serialization 1130 * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 1131 * {@code int} field {@code maximumFractionDigits} is used instead. 1132 * When writing to a stream, {@code maxFractionDigits} is set to 1133 * {@code maximumFractionDigits} or {@code Byte.MAX_VALUE}, 1134 * whichever is smaller. When reading from a stream, this field is used 1135 * only if {@code serialVersionOnStream} is less than 1. 1136 * 1137 * @serial 1138 * @see #getMaximumFractionDigits 1139 */ 1140 private byte maxFractionDigits = 3; // invariant, >= minFractionDigits 1141 1142 /** 1143 * The minimum number of digits allowed in the fractional portion of a 1144 * number. {@code minimumFractionDigits} must be less than or equal to 1145 * {@code maximumFractionDigits}. 1146 * <p> 1147 * <strong>Note:</strong> This field exists only for serialization 1148 * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 1149 * {@code int} field {@code minimumFractionDigits} is used instead. 1150 * When writing to a stream, {@code minFractionDigits} is set to 1151 * {@code minimumFractionDigits} or {@code Byte.MAX_VALUE}, 1152 * whichever is smaller. When reading from a stream, this field is used 1153 * only if {@code serialVersionOnStream} is less than 1. 1154 * 1155 * @serial 1156 * @see #getMinimumFractionDigits 1157 */ 1158 private byte minFractionDigits = 0; 1159 1160 /** 1161 * True if this format will parse numbers as integers only. 1162 * 1163 * @serial 1164 * @see #isParseIntegerOnly 1165 */ 1166 private boolean parseIntegerOnly = false; 1167 1168 // new fields for 1.2. byte is too small for integer digits. 1169 1170 /** 1171 * The maximum number of digits allowed in the integer portion of a 1172 * number. {@code maximumIntegerDigits} must be greater than or equal to 1173 * {@code minimumIntegerDigits}. 1174 * 1175 * @serial 1176 * @since 1.2 1177 * @see #getMaximumIntegerDigits 1178 */ 1179 private int maximumIntegerDigits = 40; 1180 1181 /** 1182 * The minimum number of digits allowed in the integer portion of a 1183 * number. {@code minimumIntegerDigits} must be less than or equal to 1184 * {@code maximumIntegerDigits}. 1185 * 1186 * @serial 1187 * @since 1.2 1188 * @see #getMinimumIntegerDigits 1189 */ 1190 private int minimumIntegerDigits = 1; 1191 1192 /** 1193 * The maximum number of digits allowed in the fractional portion of a 1194 * number. {@code maximumFractionDigits} must be greater than or equal to 1195 * {@code minimumFractionDigits}. 1196 * 1197 * @serial 1198 * @since 1.2 1199 * @see #getMaximumFractionDigits 1200 */ 1201 private int maximumFractionDigits = 3; // invariant, >= minFractionDigits 1202 1203 /** 1204 * The minimum number of digits allowed in the fractional portion of a 1205 * number. {@code minimumFractionDigits} must be less than or equal to 1206 * {@code maximumFractionDigits}. 1207 * 1208 * @serial 1209 * @since 1.2 1210 * @see #getMinimumFractionDigits 1211 */ 1212 private int minimumFractionDigits = 0; 1213 1214 static final int currentSerialVersion = 1; 1215 1216 /** 1217 * Describes the version of {@code NumberFormat} present on the stream. 1218 * Possible values are: 1219 * <ul> 1220 * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format. 1221 * In this version, the {@code int} fields such as 1222 * {@code maximumIntegerDigits} were not present, and the {@code byte} 1223 * fields such as {@code maxIntegerDigits} are used instead. 1224 * 1225 * <li><b>1</b>: the 1.2 version of the stream format. The values of the 1226 * {@code byte} fields such as {@code maxIntegerDigits} are ignored, 1227 * and the {@code int} fields such as {@code maximumIntegerDigits} 1228 * are used instead. 1229 * </ul> 1230 * When streaming out a {@code NumberFormat}, the most recent format 1231 * (corresponding to the highest allowable {@code serialVersionOnStream}) 1232 * is always written. 1233 * 1234 * @serial 1235 * @since 1.2 1236 */ 1237 private int serialVersionOnStream = currentSerialVersion; 1238 1239 // Removed "implements Cloneable" clause. Needs to update serialization 1240 // ID for backward compatibility. 1241 @java.io.Serial 1242 static final long serialVersionUID = -2308460125733713944L; 1243 1244 1245 // 1246 // class for AttributedCharacterIterator attributes 1247 // 1248 /** 1249 * Defines constants that are used as attribute keys in the 1250 * {@code AttributedCharacterIterator} returned 1251 * from {@code NumberFormat.formatToCharacterIterator} and as 1252 * field identifiers in {@code FieldPosition}. 1253 * 1254 * @since 1.4 1255 */ 1256 public static class Field extends Format.Field { 1257 1258 // Proclaim serial compatibility with 1.4 FCS 1259 @java.io.Serial 1260 private static final long serialVersionUID = 7494728892700160890L; 1261 1262 // table of all instances in this class, used by readResolve 1263 private static final Map<String, Field> instanceMap = new HashMap<>(11); 1264 1265 /** 1266 * Creates a Field instance with the specified 1267 * name. 1268 * 1269 * @param name Name of the attribute 1270 */ Field(String name)1271 protected Field(String name) { 1272 super(name); 1273 if (this.getClass() == NumberFormat.Field.class) { 1274 instanceMap.put(name, this); 1275 } 1276 } 1277 1278 /** 1279 * Resolves instances being deserialized to the predefined constants. 1280 * 1281 * @throws InvalidObjectException if the constant could not be resolved. 1282 * @return resolved NumberFormat.Field constant 1283 */ 1284 @Override 1285 @java.io.Serial readResolve()1286 protected Object readResolve() throws InvalidObjectException { 1287 if (this.getClass() != NumberFormat.Field.class) { 1288 throw new InvalidObjectException("subclass didn't correctly implement readResolve"); 1289 } 1290 1291 Object instance = instanceMap.get(getName()); 1292 if (instance != null) { 1293 return instance; 1294 } else { 1295 throw new InvalidObjectException("unknown attribute name"); 1296 } 1297 } 1298 1299 /** 1300 * Constant identifying the integer field. 1301 */ 1302 public static final Field INTEGER = new Field("integer"); 1303 1304 /** 1305 * Constant identifying the fraction field. 1306 */ 1307 public static final Field FRACTION = new Field("fraction"); 1308 1309 /** 1310 * Constant identifying the exponent field. 1311 */ 1312 public static final Field EXPONENT = new Field("exponent"); 1313 1314 /** 1315 * Constant identifying the decimal separator field. 1316 */ 1317 public static final Field DECIMAL_SEPARATOR = 1318 new Field("decimal separator"); 1319 1320 /** 1321 * Constant identifying the sign field. 1322 */ 1323 public static final Field SIGN = new Field("sign"); 1324 1325 /** 1326 * Constant identifying the grouping separator field. 1327 */ 1328 public static final Field GROUPING_SEPARATOR = 1329 new Field("grouping separator"); 1330 1331 /** 1332 * Constant identifying the exponent symbol field. 1333 */ 1334 public static final Field EXPONENT_SYMBOL = new 1335 Field("exponent symbol"); 1336 1337 /** 1338 * Constant identifying the percent field. 1339 */ 1340 public static final Field PERCENT = new Field("percent"); 1341 1342 /** 1343 * Constant identifying the permille field. 1344 */ 1345 public static final Field PERMILLE = new Field("per mille"); 1346 1347 /** 1348 * Constant identifying the currency field. 1349 */ 1350 public static final Field CURRENCY = new Field("currency"); 1351 1352 /** 1353 * Constant identifying the exponent sign field. 1354 */ 1355 public static final Field EXPONENT_SIGN = new Field("exponent sign"); 1356 1357 // Android-changed: Hide PREFIX field not supported by ICU. 1358 /** 1359 * Constant identifying the prefix field. 1360 * 1361 * @since 12 1362 * @hide 1363 */ 1364 public static final Field PREFIX = new Field("prefix"); 1365 1366 // Android-changed: Hide SUFFIX field not supported by ICU. 1367 /** 1368 * Constant identifying the suffix field. 1369 * 1370 * @since 12 1371 * @hide 1372 */ 1373 public static final Field SUFFIX = new Field("suffix"); 1374 } 1375 1376 1377 // Android-changed: Make unsupported Style private and removed the enum values. 1378 /** 1379 * A number format style. 1380 * <p> 1381 * {@code Style} is an enum which represents the style for formatting 1382 * a number within a given {@code NumberFormat} instance. 1383 * @since 12 1384 */ 1385 private enum Style { 1386 1387 /** 1388 * The {@code SHORT} number format style. 1389 *//* 1390 SHORT, 1391 1392 *//** 1393 * The {@code LONG} number format style. 1394 *//* 1395 LONG 1396 */ 1397 1398 } 1399 } 1400