1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18// BEGIN android-note 19// The icu implementation used was changed from icu4j to icu4jni. 20// END android-note 21 22package java.text; 23 24import java.io.IOException; 25import java.io.ObjectInputStream; 26import java.io.ObjectOutputStream; 27import java.io.ObjectStreamField; 28import java.math.BigDecimal; 29import java.math.BigInteger; 30import java.security.AccessController; 31import java.security.PrivilegedAction; 32import java.util.Currency; 33import java.util.Locale; 34 35import com.ibm.icu4jni.text.NativeDecimalFormat; 36import com.ibm.icu4jni.util.LocaleData; 37 38/** 39 * A concrete subclass of {@link NumberFormat} that formats decimal numbers. It 40 * has a variety of features designed to make it possible to parse and format 41 * numbers in any locale, including support for Western, Arabic, or Indic 42 * digits. It also supports different flavors of numbers, including integers 43 * ("123"), fixed-point numbers ("123.4"), scientific notation ("1.23E4"), 44 * percentages ("12%"), and currency amounts ("$123"). All of these flavors can 45 * be easily localized. 46 * <p> 47 * <strong>This is an enhanced version of {@code DecimalFormat} that is based on 48 * the standard version in the RI. New or changed functionality is labeled 49 * <strong><font color="red">NEW</font></strong>.</strong> 50 * <p> 51 * To obtain a {@link NumberFormat} for a specific locale (including the default 52 * locale), call one of {@code NumberFormat}'s factory methods such as 53 * {@code NumberFormat.getInstance}. Do not call the {@code DecimalFormat} 54 * constructors directly, unless you know what you are doing, since the 55 * {@link NumberFormat} factory methods may return subclasses other than 56 * {@code DecimalFormat}. If you need to customize the format object, do 57 * something like this: <blockquote> 58 * 59 * <pre> 60 * NumberFormat f = NumberFormat.getInstance(loc); 61 * if (f instanceof DecimalFormat) { 62 * ((DecimalFormat)f).setDecimalSeparatorAlwaysShown(true); 63 * } 64 * </pre> 65 * 66 * </blockquote> 67 * <h5>Example:</h5> 68 * <blockquote> 69 * 70 * <pre> 71 * // Print out a number using the localized number, currency, 72 * // and percent format for each locale 73 * Locale[] locales = NumberFormat.getAvailableLocales(); 74 * double myNumber = -1234.56; 75 * NumberFormat format; 76 * for (int j = 0; j < 3; ++j) { 77 * System.out.println("FORMAT"); 78 * for (int i = 0; i < locales.length; ++i) { 79 * if (locales[i].getCountry().length() == 0) { 80 * // Skip language-only locales 81 * continue; 82 * } 83 * System.out.print(locales[i].getDisplayName()); 84 * switch (j) { 85 * case 0: 86 * format = NumberFormat.getInstance(locales[i]); 87 * break; 88 * case 1: 89 * format = NumberFormat.getCurrencyInstance(locales[i]); 90 * break; 91 * default: 92 * format = NumberFormat.getPercentInstance(locales[i]); 93 * break; 94 * } 95 * try { 96 * // Assume format is a DecimalFormat 97 * System.out.print(": "; + ((DecimalFormat)format).toPattern() + " -> " 98 * + form.format(myNumber)); 99 * } catch (Exception e) { 100 * } 101 * try { 102 * System.out.println(" -> " + format.parse(form.format(myNumber))); 103 * } catch (ParseException e) { 104 * } 105 * } 106 * } 107 * </pre> 108 * 109 * </blockquote> 110 * <h4>Patterns</h4> 111 * <p> 112 * A {@code DecimalFormat} consists of a <em>pattern</em> and a set of 113 * <em>symbols</em>. The pattern may be set directly using 114 * {@link #applyPattern(String)}, or indirectly using other API methods which 115 * manipulate aspects of the pattern, such as the minimum number of integer 116 * digits. The symbols are stored in a {@link DecimalFormatSymbols} object. When 117 * using the {@link NumberFormat} factory methods, the pattern and symbols are 118 * read from ICU's locale data. 119 * <h4>Special Pattern Characters</h4> 120 * <p> 121 * Many characters in a pattern are taken literally; they are matched during 122 * parsing and are written out unchanged during formatting. On the other hand, 123 * special characters stand for other characters, strings, or classes of 124 * characters. For example, the '#' character is replaced by a localized digit. 125 * Often the replacement character is the same as the pattern character; in the 126 * U.S. locale, the ',' grouping character is replaced by ','. However, the 127 * replacement is still happening, and if the symbols are modified, the grouping 128 * character changes. Some special characters affect the behavior of the 129 * formatter by their presence; for example, if the percent character is seen, 130 * then the value is multiplied by 100 before being displayed. 131 * <p> 132 * To insert a special character in a pattern as a literal, that is, without any 133 * special meaning, the character must be quoted. There are some exceptions to 134 * this which are noted below. 135 * <p> 136 * The characters listed here are used in non-localized patterns. Localized 137 * patterns use the corresponding characters taken from this formatter's 138 * {@link DecimalFormatSymbols} object instead, and these characters lose their 139 * special status. Two exceptions are the currency sign and quote, which are not 140 * localized. 141 * <blockquote> <table border="0" cellspacing="3" cellpadding="0" summary="Chart 142 * showing symbol, location, localized, and meaning."> 143 * <tr bgcolor="#ccccff"> 144 * <th align="left">Symbol</th> 145 * <th align="left">Location</th> 146 * <th align="left">Localized?</th> 147 * <th align="left">Meaning</th> 148 * </tr> 149 * <tr valign="top"> 150 * <td>{@code 0}</td> 151 * <td>Number</td> 152 * <td>Yes</td> 153 * <td>Digit.</td> 154 * </tr> 155 * <tr valign="top"> 156 * <td>{@code @}</td> 157 * <td>Number</td> 158 * <td>No</td> 159 * <td><strong><font color="red">NEW</font> </strong> Significant 160 * digit.</td> 161 * </tr> 162 * <tr valign="top" bgcolor="#eeeeff"> 163 * <td>{@code #}</td> 164 * <td>Number</td> 165 * <td>Yes</td> 166 * <td>Digit, leading zeroes are not shown.</td> 167 * </tr> 168 * <tr valign="top"> 169 * <td>{@code .}</td> 170 * <td>Number</td> 171 * <td>Yes</td> 172 * <td>Decimal separator or monetary decimal separator.</td> 173 * </tr> 174 * <tr valign="top" bgcolor="#eeeeff"> 175 * <td>{@code -}</td> 176 * <td>Number</td> 177 * <td>Yes</td> 178 * <td>Minus sign.</td> 179 * </tr> 180 * <tr valign="top"> 181 * <td>{@code ,}</td> 182 * <td>Number</td> 183 * <td>Yes</td> 184 * <td>Grouping separator.</td> 185 * </tr> 186 * <tr valign="top" bgcolor="#eeeeff"> 187 * <td>{@code E}</td> 188 * <td>Number</td> 189 * <td>Yes</td> 190 * <td>Separates mantissa and exponent in scientific notation. 191 * <em>Does not need to be quoted in prefix or suffix.</em></td> 192 * </tr> 193 * <tr valign="top"> 194 * <td>{@code +}</td> 195 * <td>Exponent</td> 196 * <td>Yes</td> 197 * <td><strong><font color="red">NEW</font> </strong> Prefix 198 * positive exponents with localized plus sign. 199 * <em>Does not need to be quoted in prefix or suffix.</em></td> 200 * </tr> 201 * <tr valign="top" bgcolor="#eeeeff"> 202 * <td>{@code ;}</td> 203 * <td>Subpattern boundary</td> 204 * <td>Yes</td> 205 * <td>Separates positive and negative subpatterns.</td> 206 * </tr> 207 * <tr valign="top"> 208 * <td>{@code %}</td> 209 * <td>Prefix or suffix</td> 210 * <td>Yes</td> 211 * <td>Multiply by 100 and show as percentage.</td> 212 * </tr> 213 * <tr valign="top" bgcolor="#eeeeff"> 214 * <td>{@code \u2030} ({@code \u2030})</td> 215 * <td>Prefix or suffix</td> 216 * <td>Yes</td> 217 * <td>Multiply by 1000 and show as per mille.</td> 218 * </tr> 219 * <tr valign="top"> 220 * <td>{@code ¤} ({@code \u00A4})</td> 221 * <td>Prefix or suffix</td> 222 * <td>No</td> 223 * <td>Currency sign, replaced by currency symbol. If doubled, replaced by 224 * international currency symbol. If present in a pattern, the monetary decimal 225 * separator is used instead of the decimal separator.</td> 226 * </tr> 227 * <tr valign="top" bgcolor="#eeeeff"> 228 * <td>{@code '}</td> 229 * <td>Prefix or suffix</td> 230 * <td>No</td> 231 * <td>Used to quote special characters in a prefix or suffix, for example, 232 * {@code "'#'#"} formats 123 to {@code "#123"}. To create a single quote 233 * itself, use two in a row: {@code "# o''clock"}.</td> 234 * </tr> 235 * <tr valign="top"> 236 * <td>{@code *}</td> 237 * <td>Prefix or suffix boundary</td> 238 * <td>Yes</td> 239 * <td><strong><font color="red">NEW</font> </strong> Pad escape, 240 * precedes pad character. </td> 241 * </tr> 242 * </table> </blockquote> 243 * <p> 244 * A {@code DecimalFormat} pattern contains a postive and negative subpattern, 245 * for example, "#,##0.00;(#,##0.00)". Each subpattern has a prefix, a numeric 246 * part and a suffix. If there is no explicit negative subpattern, the negative 247 * subpattern is the localized minus sign prefixed to the positive subpattern. 248 * That is, "0.00" alone is equivalent to "0.00;-0.00". If there is an explicit 249 * negative subpattern, it serves only to specify the negative prefix and 250 * suffix; the number of digits, minimal digits, and other characteristics are 251 * ignored in the negative subpattern. This means that "#,##0.0#;(#)" produces 252 * precisely the same result as "#,##0.0#;(#,##0.0#)". 253 * <p> 254 * The prefixes, suffixes, and various symbols used for infinity, digits, 255 * thousands separators, decimal separators, etc. may be set to arbitrary 256 * values, and they will appear properly during formatting. However, care must 257 * be taken that the symbols and strings do not conflict, or parsing will be 258 * unreliable. For example, either the positive and negative prefixes or the 259 * suffixes must be distinct for {@link #parse} to be able to distinguish 260 * positive from negative values. Another example is that the decimal separator 261 * and thousands separator should be distinct characters, or parsing will be 262 * impossible. 263 * <p> 264 * The <em>grouping separator</em> is a character that separates clusters of 265 * integer digits to make large numbers more legible. It is commonly used for 266 * thousands, but in some locales it separates ten-thousands. The <em>grouping 267 * size</em> 268 * is the number of digits between the grouping separators, such as 3 for 269 * "100,000,000" or 4 for "1 0000 0000". There are actually two different 270 * grouping sizes: One used for the least significant integer digits, the 271 * <em>primary grouping size</em>, and one used for all others, the 272 * <em>secondary grouping size</em>. In most locales these are the same, but 273 * sometimes they are different. For example, if the primary grouping interval 274 * is 3, and the secondary is 2, then this corresponds to the pattern 275 * "#,##,##0", and the number 123456789 is formatted as "12,34,56,789". If a 276 * pattern contains multiple grouping separators, the interval between the last 277 * one and the end of the integer defines the primary grouping size, and the 278 * interval between the last two defines the secondary grouping size. All others 279 * are ignored, so "#,##,###,####", "###,###,####" and "##,#,###,####" produce 280 * the same result. 281 * <p> 282 * Illegal patterns, such as "#.#.#" or "#.###,###", will cause 283 * {@code DecimalFormat} to throw an {@link IllegalArgumentException} with a 284 * message that describes the problem. 285 * <h4>Pattern BNF</h4> 286 * 287 * <pre> 288 * pattern := subpattern (';' subpattern)? 289 * subpattern := prefix? number exponent? suffix? 290 * number := (integer ('.' fraction)?) | sigDigits 291 * prefix := '\\u0000'..'\\uFFFD' - specialCharacters 292 * suffix := '\\u0000'..'\\uFFFD' - specialCharacters 293 * integer := '#'* '0'* '0' 294 * fraction := '0'* '#'* 295 * sigDigits := '#'* '@' '@'* '#'* 296 * exponent := 'E' '+'? '0'* '0' 297 * padSpec := '*' padChar 298 * padChar := '\\u0000'..'\\uFFFD' - quote 299 * 300 * Notation: 301 * X* 0 or more instances of X 302 * X? 0 or 1 instances of X 303 * X|Y either X or Y 304 * C..D any character from C up to D, inclusive 305 * S-T characters in S, except those in T 306 * </pre> 307 * 308 * The first subpattern is for positive numbers. The second (optional) 309 * subpattern is for negative numbers. 310 * <p> 311 * Not indicated in the BNF syntax above: 312 * <ul> 313 * <li>The grouping separator ',' can occur inside the integer and sigDigits 314 * elements, between any two pattern characters of that element, as long as the 315 * integer or sigDigits element is not followed by the exponent element. 316 * <li><font color="red"><strong>NEW</strong> </font> Two 317 * grouping intervals are recognized: The one between the decimal point and the 318 * first grouping symbol and the one between the first and second grouping 319 * symbols. These intervals are identical in most locales, but in some locales 320 * they differ. For example, the pattern "#,##,###" formats the number 321 * 123456789 as "12,34,56,789".</li> 322 * <li> <strong><font color="red">NEW</font> </strong> The pad 323 * specifier {@code padSpec} may appear before the prefix, after the prefix, 324 * before the suffix, after the suffix or not at all. 325 * </ul> 326 * <h4>Parsing</h4> 327 * <p> 328 * {@code DecimalFormat} parses all Unicode characters that represent decimal 329 * digits, as defined by {@link Character#digit(int, int)}. In addition, 330 * {@code DecimalFormat} also recognizes as digits the ten consecutive 331 * characters starting with the localized zero digit defined in the 332 * {@link DecimalFormatSymbols} object. During formatting, the 333 * {@link DecimalFormatSymbols}-based digits are written out. 334 * <p> 335 * During parsing, grouping separators are ignored. 336 * <p> 337 * If {@link #parse(String, ParsePosition)} fails to parse a string, it returns 338 * {@code null} and leaves the parse position unchanged. 339 * <h4>Formatting</h4> 340 * <p> 341 * Formatting is guided by several parameters, all of which can be specified 342 * either using a pattern or using the API. The following description applies to 343 * formats that do not use <a href="#sci">scientific notation</a> or <a 344 * href="#sigdig">significant digits</a>. 345 * <ul> 346 * <li>If the number of actual integer digits exceeds the 347 * <em>maximum integer digits</em>, then only the least significant digits 348 * are shown. For example, 1997 is formatted as "97" if maximum integer digits 349 * is set to 2. 350 * <li>If the number of actual integer digits is less than the 351 * <em>minimum integer digits</em>, then leading zeros are added. For 352 * example, 1997 is formatted as "01997" if minimum integer digits is set to 5. 353 * <li>If the number of actual fraction digits exceeds the <em>maximum 354 * fraction digits</em>, 355 * then half-even rounding is performed to the maximum fraction digits. For 356 * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2. 357 * <li>If the number of actual fraction digits is less than the 358 * <em>minimum fraction digits</em>, then trailing zeros are added. For 359 * example, 0.125 is formatted as "0.1250" if the mimimum fraction digits is set 360 * to 4. 361 * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> 362 * positions after the decimal, where <em>j</em> is less than the maximum 363 * fraction digits. For example, 0.10004 is formatted as "0.1" if the maximum 364 * fraction digits is four or less. 365 * </ul> 366 * <p> 367 * <strong>Special Values</strong> 368 * <p> 369 * {@code NaN} is represented as a single character, typically 370 * {@code \uFFFD}. This character is determined by the 371 * {@link DecimalFormatSymbols} object. This is the only value for which the 372 * prefixes and suffixes are not used. 373 * <p> 374 * Infinity is represented as a single character, typically {@code \u221E}, 375 * with the positive or negative prefixes and suffixes applied. The infinity 376 * character is determined by the {@link DecimalFormatSymbols} object. <a 377 * name="sci"> 378 * <h4>Scientific Notation</h4> 379 * </a> 380 * <p> 381 * Numbers in scientific notation are expressed as the product of a mantissa and 382 * a power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. 383 * The mantissa is typically in the half-open interval [1.0, 10.0) or sometimes 384 * [0.0, 1.0), but it does not need to be. {@code DecimalFormat} supports 385 * arbitrary mantissas. {@code DecimalFormat} can be instructed to use 386 * scientific notation through the API or through the pattern. In a pattern, the 387 * exponent character immediately followed by one or more digit characters 388 * indicates scientific notation. Example: "0.###E0" formats the number 1234 as 389 * "1.234E3". 390 * <ul> 391 * <li>The number of digit characters after the exponent character gives the 392 * minimum exponent digit count. There is no maximum. Negative exponents are 393 * formatted using the localized minus sign, <em>not</em> the prefix and 394 * suffix from the pattern. This allows patterns such as "0.###E0 m/s". To 395 * prefix positive exponents with a localized plus sign, specify '+' between the 396 * exponent and the digits: "0.###E+0" will produce formats "1E+1", "1E+0", 397 * "1E-1", etc. (In localized patterns, use the localized plus sign rather than 398 * '+'.) 399 * <li>The minimum number of integer digits is achieved by adjusting the 400 * exponent. Example: 0.00123 formatted with "00.###E0" yields "12.3E-4". This 401 * only happens if there is no maximum number of integer digits. If there is a 402 * maximum, then the minimum number of integer digits is fixed at one. 403 * <li>The maximum number of integer digits, if present, specifies the exponent 404 * grouping. The most common use of this is to generate <em>engineering 405 * notation</em>, 406 * in which the exponent is a multiple of three, e.g., "##0.###E0". The number 407 * 12345 is formatted using "##0.###E0" as "12.345E3". 408 * <li>When using scientific notation, the formatter controls the digit counts 409 * using significant digits logic. The maximum number of significant digits 410 * limits the total number of integer and fraction digits that will be shown in 411 * the mantissa; it does not affect parsing. For example, 12345 formatted with 412 * "##0.##E0" is "12.3E3". See the section on significant digits for more 413 * details. 414 * <li>The number of significant digits shown is determined as follows: If no 415 * significant digits are used in the pattern then the minimum number of 416 * significant digits shown is one, the maximum number of significant digits 417 * shown is the sum of the <em>minimum integer</em> and 418 * <em>maximum fraction</em> digits, and it is unaffected by the maximum 419 * integer digits. If this sum is zero, then all significant digits are shown. 420 * If significant digits are used in the pattern then the number of integer 421 * digits is fixed at one and there is no exponent grouping. 422 * <li>Exponential patterns may not contain grouping separators. 423 * </ul> 424 * <a name="sigdig"> 425 * <h4> <strong><font color="red">NEW</font> </strong> Significant 426 * Digits</h4> 427 * <p> 428 * </a> {@code DecimalFormat} has two ways of controlling how many digits are 429 * shown: (a) significant digit counts or (b) integer and fraction digit counts. 430 * Integer and fraction digit counts are described above. When a formatter uses 431 * significant digits counts, the number of integer and fraction digits is not 432 * specified directly, and the formatter settings for these counts are ignored. 433 * Instead, the formatter uses as many integer and fraction digits as required 434 * to display the specified number of significant digits. 435 * <h5>Examples:</h5> 436 * <blockquote> <table border=0 cellspacing=3 cellpadding=0> 437 * <tr bgcolor="#ccccff"> 438 * <th align="left">Pattern</th> 439 * <th align="left">Minimum significant digits</th> 440 * <th align="left">Maximum significant digits</th> 441 * <th align="left">Number</th> 442 * <th align="left">Output of format()</th> 443 * </tr> 444 * <tr valign="top"> 445 * <td>{@code @@@} 446 * <td>3</td> 447 * <td>3</td> 448 * <td>12345</td> 449 * <td>{@code 12300}</td> 450 * </tr> 451 * <tr valign="top" bgcolor="#eeeeff"> 452 * <td>{@code @@@}</td> 453 * <td>3</td> 454 * <td>3</td> 455 * <td>0.12345</td> 456 * <td>{@code 0.123}</td> 457 * </tr> 458 * <tr valign="top"> 459 * <td>{@code @@##}</td> 460 * <td>2</td> 461 * <td>4</td> 462 * <td>3.14159</td> 463 * <td>{@code 3.142}</td> 464 * </tr> 465 * <tr valign="top" bgcolor="#eeeeff"> 466 * <td>{@code @@##}</td> 467 * <td>2</td> 468 * <td>4</td> 469 * <td>1.23004</td> 470 * <td>{@code 1.23}</td> 471 * </tr> 472 * </table> </blockquote> 473 * <ul> 474 * <li>Significant digit counts may be expressed using patterns that specify a 475 * minimum and maximum number of significant digits. These are indicated by the 476 * {@code '@'} and {@code '#'} characters. The minimum number of significant 477 * digits is the number of {@code '@'} characters. The maximum number of 478 * significant digits is the number of {@code '@'} characters plus the number of 479 * {@code '#'} characters following on the right. For example, the pattern 480 * {@code "@@@"} indicates exactly 3 significant digits. The pattern 481 * {@code "@##"} indicates from 1 to 3 significant digits. Trailing zero digits 482 * to the right of the decimal separator are suppressed after the minimum number 483 * of significant digits have been shown. For example, the pattern {@code "@##"} 484 * formats the number 0.1203 as {@code "0.12"}. 485 * <li>If a pattern uses significant digits, it may not contain a decimal 486 * separator, nor the {@code '0'} pattern character. Patterns such as 487 * {@code "@00"} or {@code "@.###"} are disallowed. 488 * <li>Any number of {@code '#'} characters may be prepended to the left of the 489 * leftmost {@code '@'} character. These have no effect on the minimum and 490 * maximum significant digit counts, but may be used to position grouping 491 * separators. For example, {@code "#,#@#"} indicates a minimum of one 492 * significant digit, a maximum of two significant digits, and a grouping size 493 * of three. 494 * <li>In order to enable significant digits formatting, use a pattern 495 * containing the {@code '@'} pattern character. 496 * <li>In order to disable significant digits formatting, use a pattern that 497 * does not contain the {@code '@'} pattern character. 498 * <li>The number of significant digits has no effect on parsing. 499 * <li>Significant digits may be used together with exponential notation. Such 500 * patterns are equivalent to a normal exponential pattern with a minimum and 501 * maximum integer digit count of one, a minimum fraction digit count of the 502 * number of '@' characters in the pattern - 1, and a maximum fraction digit 503 * count of the number of '@' and '#' characters in the pattern - 1. For 504 * example, the pattern {@code "@@###E0"} is equivalent to {@code "0.0###E0"}. 505 * <li>If signficant digits are in use then the integer and fraction digit 506 * counts, as set via the API, are ignored. 507 * </ul> 508 * <h4> <strong><font color="red">NEW</font> </strong> Padding</h4> 509 * <p> 510 * {@code DecimalFormat} supports padding the result of {@code format} to a 511 * specific width. Padding may be specified either through the API or through 512 * the pattern syntax. In a pattern, the pad escape character followed by a 513 * single pad character causes padding to be parsed and formatted. The pad 514 * escape character is '*' in unlocalized patterns. For example, 515 * {@code "$*x#,##0.00"} formats 123 to {@code "$xx123.00"}, and 1234 to 516 * {@code "$1,234.00"}. 517 * <ul> 518 * <li>When padding is in effect, the width of the positive subpattern, 519 * including prefix and suffix, determines the format width. For example, in the 520 * pattern {@code "* #0 o''clock"}, the format width is 10.</li> 521 * <li>The width is counted in 16-bit code units (Java {@code char}s).</li> 522 * <li>Some parameters which usually do not matter have meaning when padding is 523 * used, because the pattern width is significant with padding. In the pattern "* 524 * ##,##,#,##0.##", the format width is 14. The initial characters "##,##," do 525 * not affect the grouping size or maximum integer digits, but they do affect 526 * the format width.</li> 527 * <li>Padding may be inserted at one of four locations: before the prefix, 528 * after the prefix, before the suffix or after the suffix. If padding is 529 * specified in any other location, {@link #applyPattern} throws an {@link 530 * IllegalArgumentException}. If there is no prefix, before the prefix and after 531 * the prefix are equivalent, likewise for the suffix.</li> 532 * <li>When specified in a pattern, the 16-bit {@code char} immediately 533 * following the pad escape is the pad character. This may be any character, 534 * including a special pattern character. That is, the pad escape 535 * <em>escapes</em> the following character. If there is no character after 536 * the pad escape, then the pattern is illegal.</li> 537 * </ul> 538 * <h4>Synchronization</h4> 539 * <p> 540 * {@code DecimalFormat} objects are not synchronized. Multiple threads should 541 * not access one formatter concurrently. 542 * 543 * @see Format 544 * @see NumberFormat 545 */ 546public class DecimalFormat extends NumberFormat { 547 548 private static final long serialVersionUID = 864413376551465018L; 549 550 private transient boolean parseBigDecimal = false; 551 552 private transient DecimalFormatSymbols symbols; 553 554 private transient NativeDecimalFormat dform; 555 556 /** 557 * Constructs a new {@code DecimalFormat} for formatting and parsing numbers 558 * for the default locale. 559 */ 560 public DecimalFormat() { 561 // BEGIN android-changed: reduce duplication. 562 Locale locale = Locale.getDefault(); 563 this.symbols = new DecimalFormatSymbols(locale); 564 LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale); 565 initNative(localeData.numberPattern); 566 // END android-changed 567 } 568 569 /** 570 * Constructs a new {@code DecimalFormat} using the specified non-localized 571 * pattern and the {@code DecimalFormatSymbols} for the default Locale. 572 * 573 * @param pattern 574 * the non-localized pattern. 575 * @throws IllegalArgumentException 576 * if the pattern cannot be parsed. 577 */ 578 public DecimalFormat(String pattern) { 579 // BEGIN android-changed: reduce duplication. 580 this(pattern, Locale.getDefault()); 581 // END android-changed 582 } 583 584 /** 585 * Constructs a new {@code DecimalFormat} using the specified non-localized 586 * pattern and {@code DecimalFormatSymbols}. 587 * 588 * @param pattern 589 * the non-localized pattern. 590 * @param value 591 * the DecimalFormatSymbols. 592 * @throws IllegalArgumentException 593 * if the pattern cannot be parsed. 594 */ 595 public DecimalFormat(String pattern, DecimalFormatSymbols value) { 596 // BEGIN android-changed: reduce duplication. 597 this.symbols = (DecimalFormatSymbols) value.clone(); 598 initNative(pattern); 599 // END android-changed 600 } 601 602 // BEGIN android-added: used by NumberFormat.getInstance because cloning DecimalFormatSymbols is slow. 603 DecimalFormat(String pattern, Locale locale) { 604 this.symbols = new DecimalFormatSymbols(locale); 605 initNative(pattern); 606 } 607 // END android-added 608 609 // BEGIN android-changed: reduce duplication. 610 private void initNative(String pattern) { 611 try { 612 this.dform = new NativeDecimalFormat(pattern, symbols); 613 } catch (IllegalArgumentException ex) { 614 throw new IllegalArgumentException(pattern); 615 } 616 super.setMaximumFractionDigits(dform.getMaximumFractionDigits()); 617 super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits()); 618 super.setMinimumFractionDigits(dform.getMinimumFractionDigits()); 619 super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits()); 620 } 621 // END android-added 622 623 /** 624 * Changes the pattern of this decimal format to the specified pattern which 625 * uses localized pattern characters. 626 * 627 * @param pattern 628 * the localized pattern. 629 * @throws IllegalArgumentException 630 * if the pattern cannot be parsed. 631 */ 632 public void applyLocalizedPattern(String pattern) { 633 dform.applyLocalizedPattern(pattern); 634 } 635 636 /** 637 * Changes the pattern of this decimal format to the specified pattern which 638 * uses non-localized pattern characters. 639 * 640 * @param pattern 641 * the non-localized pattern. 642 * @throws IllegalArgumentException 643 * if the pattern cannot be parsed. 644 */ 645 public void applyPattern(String pattern) { 646 dform.applyPattern(pattern); 647 } 648 649 /** 650 * Returns a new instance of {@code DecimalFormat} with the same pattern and 651 * properties as this decimal format. 652 * 653 * @return a shallow copy of this decimal format. 654 * @see java.lang.Cloneable 655 */ 656 @Override 657 public Object clone() { 658 DecimalFormat clone = (DecimalFormat) super.clone(); 659 clone.dform = (NativeDecimalFormat) dform.clone(); 660 clone.symbols = (DecimalFormatSymbols) symbols.clone(); 661 return clone; 662 } 663 664 /** 665 * Compares the specified object to this decimal format and indicates if 666 * they are equal. In order to be equal, {@code object} must be an instance 667 * of {@code DecimalFormat} with the same pattern and properties. 668 * 669 * @param object 670 * the object to compare with this object. 671 * @return {@code true} if the specified object is equal to this decimal 672 * format; {@code false} otherwise. 673 * @see #hashCode 674 */ 675 @Override 676 public boolean equals(Object object) { 677 if (this == object) { 678 return true; 679 } 680 if (!(object instanceof DecimalFormat)) { 681 return false; 682 } 683 DecimalFormat other = (DecimalFormat) object; 684 return (this.dform == null ? other.dform == null : this.dform.equals(other.dform)) && 685 getDecimalFormatSymbols().equals(other.getDecimalFormatSymbols()); 686 } 687 688 /** 689 * Formats the specified object using the rules of this decimal format and 690 * returns an {@code AttributedCharacterIterator} with the formatted number 691 * and attributes. 692 * 693 * @param object 694 * the object to format. 695 * @return an AttributedCharacterIterator with the formatted number and 696 * attributes. 697 * @throws IllegalArgumentException 698 * if {@code object} cannot be formatted by this format. 699 * @throws NullPointerException 700 * if {@code object} is {@code null}. 701 */ 702 @Override 703 public AttributedCharacterIterator formatToCharacterIterator(Object object) { 704 if (object == null) { 705 throw new NullPointerException(); 706 } 707 return dform.formatToCharacterIterator(object); 708 } 709 710 @Override 711 public StringBuffer format(double value, StringBuffer buffer, FieldPosition position) { 712 return dform.format(value, buffer, position); 713 } 714 715 @Override 716 public StringBuffer format(long value, StringBuffer buffer, FieldPosition position) { 717 return dform.format(value, buffer, position); 718 } 719 720 @Override 721 public final StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) { 722 if (number instanceof BigInteger) { 723 BigInteger bigInteger = (BigInteger) number; 724 if (bigInteger.bitLength() < 64) { 725 return dform.format(bigInteger.longValue(), toAppendTo, pos); 726 } else { 727 return dform.formatBigInteger(bigInteger, toAppendTo, pos); 728 } 729 } else if (number instanceof BigDecimal) { 730 return dform.formatBigDecimal((BigDecimal) number, toAppendTo, pos); 731 } 732 return super.format(number, toAppendTo, pos); 733 } 734 735 /** 736 * Returns the {@code DecimalFormatSymbols} used by this decimal format. 737 * 738 * @return a copy of the {@code DecimalFormatSymbols} used by this decimal 739 * format. 740 */ 741 public DecimalFormatSymbols getDecimalFormatSymbols() { 742 return (DecimalFormatSymbols) symbols.clone(); 743 } 744 745 /** 746 * Returns the currency used by this decimal format. 747 * 748 * @return the currency used by this decimal format. 749 * @see DecimalFormatSymbols#getCurrency() 750 */ 751 @Override 752 public Currency getCurrency() { 753 return symbols.getCurrency(); 754 } 755 756 /** 757 * Returns the number of digits grouped together by the grouping separator. 758 * This only allows to get the primary grouping size. There is no API to get 759 * the secondary grouping size. 760 * 761 * @return the number of digits grouped together. 762 */ 763 public int getGroupingSize() { 764 return dform.getGroupingSize(); 765 } 766 767 /** 768 * Returns the multiplier which is applied to the number before formatting 769 * or after parsing. 770 * 771 * @return the multiplier. 772 */ 773 public int getMultiplier() { 774 return dform.getMultiplier(); 775 } 776 777 /** 778 * Returns the prefix which is formatted or parsed before a negative number. 779 * 780 * @return the negative prefix. 781 */ 782 public String getNegativePrefix() { 783 return dform.getNegativePrefix(); 784 } 785 786 /** 787 * Returns the suffix which is formatted or parsed after a negative number. 788 * 789 * @return the negative suffix. 790 */ 791 public String getNegativeSuffix() { 792 return dform.getNegativeSuffix(); 793 } 794 795 /** 796 * Returns the prefix which is formatted or parsed before a positive number. 797 * 798 * @return the positive prefix. 799 */ 800 public String getPositivePrefix() { 801 return dform.getPositivePrefix(); 802 } 803 804 /** 805 * Returns the suffix which is formatted or parsed after a positive number. 806 * 807 * @return the positive suffix. 808 */ 809 public String getPositiveSuffix() { 810 return dform.getPositiveSuffix(); 811 } 812 813 @Override 814 public int hashCode() { 815 return dform.hashCode(); 816 } 817 818 /** 819 * Indicates whether the decimal separator is shown when there are no 820 * fractional digits. 821 * 822 * @return {@code true} if the decimal separator should always be formatted; 823 * {@code false} otherwise. 824 */ 825 public boolean isDecimalSeparatorAlwaysShown() { 826 return dform.isDecimalSeparatorAlwaysShown(); 827 } 828 829 /** 830 * This value indicates whether the return object of the parse operation is 831 * of type {@code BigDecimal}. This value defaults to {@code false}. 832 * 833 * @return {@code true} if parse always returns {@code BigDecimals}, 834 * {@code false} if the type of the result is {@code Long} or 835 * {@code Double}. 836 */ 837 public boolean isParseBigDecimal() { 838 return this.parseBigDecimal; 839 } 840 841 /** 842 * Sets the flag that indicates whether numbers will be parsed as integers. 843 * When this decimal format is used for parsing and this value is set to 844 * {@code true}, then the resulting numbers will be of type 845 * {@code java.lang.Integer}. Special cases are NaN, positive and negative 846 * infinity, which are still returned as {@code java.lang.Double}. 847 * 848 * 849 * @param value 850 * {@code true} that the resulting numbers of parse operations 851 * will be of type {@code java.lang.Integer} except for the 852 * special cases described above. 853 */ 854 @Override 855 public void setParseIntegerOnly(boolean value) { 856 // In this implementation, NativeDecimalFormat is wrapped to 857 // fulfill most of the format and parse feature. And this method is 858 // delegated to the wrapped instance of NativeDecimalFormat. 859 dform.setParseIntegerOnly(value); 860 } 861 862 /** 863 * Indicates whether parsing with this decimal format will only 864 * return numbers of type {@code java.lang.Integer}. 865 * 866 * @return {@code true} if this {@code DecimalFormat}'s parse method only 867 * returns {@code java.lang.Integer}; {@code false} otherwise. 868 */ 869 @Override 870 public boolean isParseIntegerOnly() { 871 return dform.isParseIntegerOnly(); 872 } 873 874 private static final Double NEGATIVE_ZERO_DOUBLE = new Double(-0.0); 875 876 /** 877 * Parses a {@code Long} or {@code Double} from the specified string 878 * starting at the index specified by {@code position}. If the string is 879 * successfully parsed then the index of the {@code ParsePosition} is 880 * updated to the index following the parsed text. On error, the index is 881 * unchanged and the error index of {@code ParsePosition} is set to the 882 * index where the error occurred. 883 * 884 * @param string 885 * the string to parse. 886 * @param position 887 * input/output parameter, specifies the start index in 888 * {@code string} from where to start parsing. If parsing is 889 * successful, it is updated with the index following the parsed 890 * text; on error, the index is unchanged and the error index is 891 * set to the index where the error occurred. 892 * @return a {@code Long} or {@code Double} resulting from the parse or 893 * {@code null} if there is an error. The result will be a 894 * {@code Long} if the parsed number is an integer in the range of a 895 * long, otherwise the result is a {@code Double}. If 896 * {@code isParseBigDecimal} is {@code true} then it returns the 897 * result as a {@code BigDecimal}. 898 */ 899 @Override 900 public Number parse(String string, ParsePosition position) { 901 Number number = dform.parse(string, position); 902 if (null == number) { 903 return null; 904 } 905 // BEGIN android-removed 906 // if (this.isParseBigDecimal()) { 907 // if (number instanceof Long) { 908 // return new BigDecimal(number.longValue()); 909 // } 910 // if ((number instanceof Double) && !((Double) number).isInfinite() 911 // && !((Double) number).isNaN()) { 912 // 913 // return new BigDecimal(number.doubleValue()); 914 // } 915 // if (number instanceof BigInteger) { 916 // return new BigDecimal(number.doubleValue()); 917 // } 918 // if (number instanceof com.ibm.icu.math.BigDecimal) { 919 // return new BigDecimal(number.toString()); 920 // } 921 // return number; 922 // } 923 // if ((number instanceof com.ibm.icu.math.BigDecimal) 924 // || (number instanceof BigInteger)) { 925 // return new Double(number.doubleValue()); 926 // } 927 // END android-removed 928 // BEGIN android-added 929 if (this.isParseBigDecimal()) { 930 if (number instanceof Long) { 931 return new BigDecimal(number.longValue()); 932 } 933 if ((number instanceof Double) && !((Double) number).isInfinite() 934 && !((Double) number).isNaN()) { 935 936 return new BigDecimal(number.toString()); 937 } 938 if (number instanceof BigInteger) { 939 return new BigDecimal(number.toString()); 940 } 941 return number; 942 } 943 if ((number instanceof BigDecimal) || (number instanceof BigInteger)) { 944 return new Double(number.doubleValue()); 945 } 946 // END android-added 947 948 if (this.isParseIntegerOnly() && number.equals(NEGATIVE_ZERO_DOUBLE)) { 949 return Long.valueOf(0); // android-changed 950 } 951 return number; 952 953 } 954 955 /** 956 * Sets the {@code DecimalFormatSymbols} used by this decimal format. 957 * 958 * @param value 959 * the {@code DecimalFormatSymbols} to set. 960 */ 961 public void setDecimalFormatSymbols(DecimalFormatSymbols value) { 962 if (value != null) { 963 // BEGIN android-changed: the Java object is canonical, and we copy down to native code. 964 this.symbols = (DecimalFormatSymbols) value.clone(); 965 dform.setDecimalFormatSymbols(this.symbols); 966 // END android-changed 967 } 968 } 969 970 /** 971 * Sets the currency used by this decimal format. The min and max fraction 972 * digits remain the same. 973 * 974 * @param currency 975 * the currency this {@code DecimalFormat} should use. 976 * @see DecimalFormatSymbols#setCurrency(Currency) 977 */ 978 @Override 979 public void setCurrency(Currency currency) { 980 // BEGIN android-changed 981 dform.setCurrency(Currency.getInstance(currency.getCurrencyCode())); 982 // END android-changed 983 symbols.setCurrency(currency); 984 } 985 986 /** 987 * Sets whether the decimal separator is shown when there are no fractional 988 * digits. 989 * 990 * @param value 991 * {@code true} if the decimal separator should always be 992 * formatted; {@code false} otherwise. 993 */ 994 public void setDecimalSeparatorAlwaysShown(boolean value) { 995 dform.setDecimalSeparatorAlwaysShown(value); 996 } 997 998 /** 999 * Sets the number of digits grouped together by the grouping separator. 1000 * This only allows to set the primary grouping size; the secondary grouping 1001 * size can only be set with a pattern. 1002 * 1003 * @param value 1004 * the number of digits grouped together. 1005 */ 1006 public void setGroupingSize(int value) { 1007 dform.setGroupingSize(value); 1008 } 1009 1010 /** 1011 * Sets whether or not grouping will be used in this format. Grouping 1012 * affects both parsing and formatting. 1013 * 1014 * @param value 1015 * {@code true} if grouping is used; {@code false} otherwise. 1016 */ 1017 @Override 1018 public void setGroupingUsed(boolean value) { 1019 dform.setGroupingUsed(value); 1020 } 1021 1022 /** 1023 * Indicates whether grouping will be used in this format. 1024 * 1025 * @return {@code true} if grouping is used; {@code false} otherwise. 1026 */ 1027 @Override 1028 public boolean isGroupingUsed() { 1029 return dform.isGroupingUsed(); 1030 } 1031 1032 /** 1033 * Sets the maximum number of digits after the decimal point. 1034 * If the value passed is negative then it is replaced by 0. 1035 * Regardless of this setting, no more than 340 digits will be used. 1036 * 1037 * @param value the maximum number of fraction digits. 1038 */ 1039 @Override 1040 public void setMaximumFractionDigits(int value) { 1041 super.setMaximumFractionDigits(value); 1042 dform.setMaximumFractionDigits(getMaximumFractionDigits()); 1043 } 1044 1045 /** 1046 * Sets the maximum number of digits before the decimal point. 1047 * If the value passed is negative then it is replaced by 0. 1048 * Regardless of this setting, no more than 309 digits will be used. 1049 * 1050 * @param value the maximum number of integer digits. 1051 */ 1052 @Override 1053 public void setMaximumIntegerDigits(int value) { 1054 super.setMaximumIntegerDigits(value); 1055 dform.setMaximumIntegerDigits(getMaximumIntegerDigits()); 1056 } 1057 1058 /** 1059 * Sets the minimum number of digits after the decimal point. 1060 * If the value passed is negative then it is replaced by 0. 1061 * Regardless of this setting, no more than 340 digits will be used. 1062 * 1063 * @param value the minimum number of fraction digits. 1064 */ 1065 @Override 1066 public void setMinimumFractionDigits(int value) { 1067 super.setMinimumFractionDigits(value); 1068 dform.setMinimumFractionDigits(getMinimumFractionDigits()); 1069 } 1070 1071 /** 1072 * Sets the minimum number of digits before the decimal point. 1073 * If the value passed is negative then it is replaced by 0. 1074 * Regardless of this setting, no more than 309 digits will be used. 1075 * 1076 * @param value the minimum number of integer digits. 1077 */ 1078 @Override 1079 public void setMinimumIntegerDigits(int value) { 1080 super.setMinimumIntegerDigits(value); 1081 dform.setMinimumIntegerDigits(getMinimumIntegerDigits()); 1082 } 1083 1084 /** 1085 * Sets the multiplier which is applied to the number before formatting or 1086 * after parsing. 1087 * 1088 * @param value 1089 * the multiplier. 1090 */ 1091 public void setMultiplier(int value) { 1092 dform.setMultiplier(value); 1093 } 1094 1095 /** 1096 * Sets the prefix which is formatted or parsed before a negative number. 1097 * 1098 * @param value 1099 * the negative prefix. 1100 */ 1101 public void setNegativePrefix(String value) { 1102 dform.setNegativePrefix(value); 1103 } 1104 1105 /** 1106 * Sets the suffix which is formatted or parsed after a negative number. 1107 * 1108 * @param value 1109 * the negative suffix. 1110 */ 1111 public void setNegativeSuffix(String value) { 1112 dform.setNegativeSuffix(value); 1113 } 1114 1115 /** 1116 * Sets the prefix which is formatted or parsed before a positive number. 1117 * 1118 * @param value 1119 * the positive prefix. 1120 */ 1121 public void setPositivePrefix(String value) { 1122 dform.setPositivePrefix(value); 1123 } 1124 1125 /** 1126 * Sets the suffix which is formatted or parsed after a positive number. 1127 * 1128 * @param value 1129 * the positive suffix. 1130 */ 1131 public void setPositiveSuffix(String value) { 1132 dform.setPositiveSuffix(value); 1133 } 1134 1135 /** 1136 * Sets the behaviour of the parse method. If set to {@code true} then all 1137 * the returned objects will be of type {@code BigDecimal}. 1138 * 1139 * @param newValue 1140 * {@code true} if all the returned objects should be of type 1141 * {@code BigDecimal}; {@code false} otherwise. 1142 */ 1143 public void setParseBigDecimal(boolean newValue) { 1144 this.parseBigDecimal = newValue; 1145 } 1146 1147 /** 1148 * Returns the pattern of this decimal format using localized pattern 1149 * characters. 1150 * 1151 * @return the localized pattern. 1152 */ 1153 public String toLocalizedPattern() { 1154 return dform.toLocalizedPattern(); 1155 } 1156 1157 /** 1158 * Returns the pattern of this decimal format using non-localized pattern 1159 * characters. 1160 * 1161 * @return the non-localized pattern. 1162 */ 1163 public String toPattern() { 1164 return dform.toPattern(); 1165 } 1166 1167 // the fields list to be serialized 1168 private static final ObjectStreamField[] serialPersistentFields = { 1169 new ObjectStreamField("positivePrefix", String.class), //$NON-NLS-1$ 1170 new ObjectStreamField("positiveSuffix", String.class), //$NON-NLS-1$ 1171 new ObjectStreamField("negativePrefix", String.class), //$NON-NLS-1$ 1172 new ObjectStreamField("negativeSuffix", String.class), //$NON-NLS-1$ 1173 new ObjectStreamField("posPrefixPattern", String.class), //$NON-NLS-1$ 1174 new ObjectStreamField("posSuffixPattern", String.class), //$NON-NLS-1$ 1175 new ObjectStreamField("negPrefixPattern", String.class), //$NON-NLS-1$ 1176 new ObjectStreamField("negSuffixPattern", String.class), //$NON-NLS-1$ 1177 new ObjectStreamField("multiplier", int.class), //$NON-NLS-1$ 1178 new ObjectStreamField("groupingSize", byte.class), //$NON-NLS-1$ 1179 // BEGIN android-added 1180 new ObjectStreamField("groupingUsed", boolean.class), //$NON-NLS-1$ 1181 // END android-added 1182 new ObjectStreamField("decimalSeparatorAlwaysShown", boolean.class), //$NON-NLS-1$ 1183 new ObjectStreamField("parseBigDecimal", boolean.class), //$NON-NLS-1$ 1184 new ObjectStreamField("symbols", DecimalFormatSymbols.class), //$NON-NLS-1$ 1185 new ObjectStreamField("useExponentialNotation", boolean.class), //$NON-NLS-1$ 1186 new ObjectStreamField("minExponentDigits", byte.class), //$NON-NLS-1$ 1187 new ObjectStreamField("maximumIntegerDigits", int.class), //$NON-NLS-1$ 1188 new ObjectStreamField("minimumIntegerDigits", int.class), //$NON-NLS-1$ 1189 new ObjectStreamField("maximumFractionDigits", int.class), //$NON-NLS-1$ 1190 new ObjectStreamField("minimumFractionDigits", int.class), //$NON-NLS-1$ 1191 new ObjectStreamField("serialVersionOnStream", int.class), }; //$NON-NLS-1$ 1192 1193 /** 1194 * Writes serialized fields following serialized forms specified by Java 1195 * specification. 1196 * 1197 * @param stream 1198 * the output stream to write serialized bytes 1199 * @throws IOException 1200 * if some I/O error occurs 1201 * @throws ClassNotFoundException 1202 */ 1203 @SuppressWarnings("nls") 1204 private void writeObject(ObjectOutputStream stream) throws IOException, 1205 ClassNotFoundException { 1206 ObjectOutputStream.PutField fields = stream.putFields(); 1207 fields.put("positivePrefix", dform.getPositivePrefix()); 1208 fields.put("positiveSuffix", dform.getPositiveSuffix()); 1209 fields.put("negativePrefix", dform.getNegativePrefix()); 1210 fields.put("negativeSuffix", dform.getNegativeSuffix()); 1211 fields.put("posPrefixPattern", (String) null); 1212 fields.put("posSuffixPattern", (String) null); 1213 fields.put("negPrefixPattern", (String) null); 1214 fields.put("negSuffixPattern", (String) null); 1215 fields.put("multiplier", dform.getMultiplier()); 1216 fields.put("groupingSize", (byte) dform.getGroupingSize()); 1217 // BEGIN android-added 1218 fields.put("groupingUsed", dform.isGroupingUsed()); 1219 // END android-added 1220 fields.put("decimalSeparatorAlwaysShown", dform 1221 .isDecimalSeparatorAlwaysShown()); 1222 fields.put("parseBigDecimal", parseBigDecimal); 1223 fields.put("symbols", symbols); 1224 fields.put("useExponentialNotation", false); 1225 fields.put("minExponentDigits", (byte) 0); 1226 fields.put("maximumIntegerDigits", dform.getMaximumIntegerDigits()); 1227 fields.put("minimumIntegerDigits", dform.getMinimumIntegerDigits()); 1228 fields.put("maximumFractionDigits", dform.getMaximumFractionDigits()); 1229 fields.put("minimumFractionDigits", dform.getMinimumFractionDigits()); 1230 fields.put("serialVersionOnStream", 3); 1231 stream.writeFields(); 1232 } 1233 1234 /** 1235 * Reads serialized fields following serialized forms specified by Java 1236 * specification. 1237 * 1238 * @param stream 1239 * the input stream to read serialized bytes 1240 * @throws IOException 1241 * if some I/O error occurs 1242 * @throws ClassNotFoundException 1243 * if some class of serialized objects or fields cannot be found 1244 */ 1245 @SuppressWarnings("nls") 1246 private void readObject(ObjectInputStream stream) throws IOException, 1247 ClassNotFoundException { 1248 1249 // BEGIN android-changed 1250 ObjectInputStream.GetField fields = stream.readFields(); 1251 this.symbols = (DecimalFormatSymbols) fields.get("symbols", null); 1252 1253 initNative(""); 1254 dform.setPositivePrefix((String) fields.get("positivePrefix", "")); 1255 dform.setPositiveSuffix((String) fields.get("positiveSuffix", "")); 1256 dform.setNegativePrefix((String) fields.get("negativePrefix", "-")); 1257 dform.setNegativeSuffix((String) fields.get("negativeSuffix", "")); 1258 dform.setMultiplier(fields.get("multiplier", 1)); 1259 dform.setGroupingSize(fields.get("groupingSize", (byte) 3)); 1260 dform.setGroupingUsed(fields.get("groupingUsed", true)); 1261 dform.setDecimalSeparatorAlwaysShown(fields.get("decimalSeparatorAlwaysShown", false)); 1262 1263 final int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309); 1264 final int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309); 1265 final int maximumFractionDigits = fields.get("maximumFractionDigits", 340); 1266 final int minimumFractionDigits = fields.get("minimumFractionDigits", 340); 1267 // BEGIN android-changed: tell ICU what we want, then ask it what we can have, and then 1268 // set that in our Java object. This isn't RI-compatible, but then very little of our 1269 // behavior in this area is, and it's not obvious how we can second-guess ICU (or tell 1270 // it to just do exactly what we ask). We only need to do this with maximumIntegerDigits 1271 // because ICU doesn't seem to have its own ideas about the other options. 1272 dform.setMaximumIntegerDigits(maximumIntegerDigits); 1273 super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits()); 1274 1275 setMinimumIntegerDigits(minimumIntegerDigits); 1276 setMinimumFractionDigits(minimumFractionDigits); 1277 setMaximumFractionDigits(maximumFractionDigits); 1278 setParseBigDecimal(fields.get("parseBigDecimal", false)); 1279 1280 if (fields.get("serialVersionOnStream", 0) < 3) { 1281 setMaximumIntegerDigits(super.getMaximumIntegerDigits()); 1282 setMinimumIntegerDigits(super.getMinimumIntegerDigits()); 1283 setMaximumFractionDigits(super.getMaximumFractionDigits()); 1284 setMinimumFractionDigits(super.getMinimumFractionDigits()); 1285 } 1286 // END android-changed 1287 } 1288} 1289