001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2017, Jean-Marie Dautelle, Werner Keil, V2COM. 004 * 005 * All rights reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without modification, 008 * are permitted provided that the following conditions are met: 009 * 010 * 1. Redistributions of source code must retain the above copyright notice, 011 * this list of conditions and the following disclaimer. 012 * 013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 014 * and the following disclaimer in the documentation and/or other materials provided with the distribution. 015 * 016 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products 017 * derived from this software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030/* 031 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved 032 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved 033 * 034 * The original version of this source code and documentation is copyrighted 035 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These 036 * materials are provided under terms of a License Agreement between Taligent 037 * and Sun. This technology is protected by multiple US and International 038 * patents. This notice and attribution to Taligent may not be removed. 039 * Taligent is a registered trademark of Taligent, Inc. 040 * 041 */ 042 043package tec.units.ri.internal.format.l10n; 044 045import java.util.Hashtable; 046 047/** 048 * A Java ME compliant backport of {@linkplain java.text.NumberFormat} <code>NumberFormat</code> has features designed to make it possible to format 049 * numbers in any locale. It also supports different kinds of numbers, including integers (123), fixed-point numbers (123.4), percentages (12%), and 050 * currency amounts ($123). All of these can be localized. 051 * 052 * Usage: 053 * 054 * <pre> 055 * NumberFormat f = NumberFormat.getInstance(); 056 * StringBuffer sb = f.format(new Double(123.45), new StringBuffer()); 057 * </pre> 058 * <p> 059 * 060 * Or eventually it's possible to change number of decimals displayed 061 * 062 * <pre> 063 * NumberFormat f = NumberFormat.getInstance(); 064 * f.setMaximumFractionDigits(2); 065 * StringBuffer sb = f.format(new Double(123.45559), new StringBuffer()); 066 * </pre> 067 * <p> 068 * <code>NumberFormat</code> helps you to format and parse numbers for any locale. Your code can be completely independent of the locale conventions 069 * for decimal points, thousands-separators, or even the particular decimal digits used, or whether the number format is even decimal. 070 * 071 * <p> 072 * To format a number for the current Locale, use one of the factory class methods: <blockquote> 073 * 074 * <pre> 075 * myString = NumberFormat.getInstance().format(myNumber); 076 * </pre> 077 * 078 * </blockquote> If you are formatting multiple numbers, it is more efficient to get the format and use it multiple times so that the system doesn't 079 * have to fetch the information about the local language and country conventions multiple times. <blockquote> 080 * 081 * <pre> 082 * NumberFormat nf = NumberFormat.getInstance(); 083 * for (int i = 0; i < a.length; ++i) { 084 * output.println(nf.format(myNumber[i]) + "; "); 085 * } 086 * </pre> 087 * 088 * </blockquote> To format a number for a different Locale, specify it in the call to <code>getInstance</code>. <blockquote> 089 * 090 * <pre> 091 * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH); 092 * </pre> 093 * 094 * </blockquote> You can also use a <code>NumberFormat</code> to parse numbers: <blockquote> 095 * 096 * <pre> 097 * myNumber = nf.parse(myString); 098 * </pre> 099 * 100 * </blockquote> Use <code>getInstance</code> or <code>getNumberInstance</code> to get the normal number format. Use <code>getIntegerInstance</code> 101 * to get an integer number format. Use <code>getCurrencyInstance</code> to get the currency number format. And use <code>getPercentInstance</code> to 102 * get a format for displaying percentages. With this format, a fraction like 0.53 is displayed as 53%. 103 * 104 * <p> 105 * You can also control the display of numbers with such methods as <code>setMinimumFractionDigits</code>. If you want even more control over the 106 * format or parsing, or want to give your users more control, you can try casting the <code>NumberFormat</code> you get from the factory methods to a 107 * <code>DecimalFormat</code>. This will work for the vast majority of locales; just remember to put it in a <code>try</code> block in case you 108 * encounter an unusual one. 109 * 110 * <p> 111 * NumberFormat and DecimalFormat are designed such that some controls work for formatting and others work for parsing. The following is the detailed 112 * description for each these control methods, 113 * <p> 114 * setParseIntegerOnly : only affects parsing, e.g. if true, "3456.78" -> 3456 (and leaves the parse position just after index 6) if false, "3456.78" 115 * -> 3456.78 (and leaves the parse position just after index 8) This is independent of formatting. If you want to not show a decimal point where 116 * there might be no digits after the decimal point, use setDecimalSeparatorAlwaysShown. 117 * <p> 118 * setDecimalSeparatorAlwaysShown : only affects formatting, and only where there might be no digits after the decimal point, such as with a pattern 119 * like "#,##0.##", e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This is independent of parsing. If you want parsing to stop at the 120 * decimal point, use setParseIntegerOnly. 121 * 122 * <p> 123 * You can also use forms of the <code>parse</code> and <code>format</code> methods with <code>ParsePosition</code> and <code>FieldPosition</code> to 124 * allow you to: 125 * <ul> 126 * <li>progressively parse through pieces of a string 127 * <li>align the decimal point and other areas 128 * </ul> 129 * For example, you can align numbers in two ways: 130 * <ol> 131 * <li>If you are using a monospaced font with spacing for alignment, you can pass the <code>FieldPosition</code> in your format call, with 132 * <code>field</code> = <code>INTEGER_FIELD</code>. On output, <code>getEndIndex</code> will be set to the offset between the last character of the 133 * integer and the decimal. Add (desiredSpaceCount - getEndIndex) spaces at the front of the string. 134 * 135 * <li>If you are using proportional fonts, instead of padding with spaces, measure the width of the string in pixels from the start to 136 * <code>getEndIndex</code>. Then move the pen by (desiredPixelWidth - widthToAlignmentPoint) before drawing the text. It also works where there is no 137 * decimal, but possibly additional characters at the end, e.g., with parentheses in negative numbers: "(12)" for -12. 138 * </ol> 139 * 140 * <h4><a name="synchronization">Synchronization</a></h4> 141 * 142 * <p> 143 * Number formats are generally not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a 144 * format concurrently, it must be synchronized externally. 145 * 146 * @version $Revision: 0.5 $ 147 * @see DecimalFormat 148 * @author Mark Davis 149 * @author Helena Shih 150 * @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a> 151 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 152 */ 153public abstract class NumberFormat extends Format { 154 155 /** 156 * Field constant used to construct a FieldPosition object. Signifies that the position of the integer part of a formatted number should be 157 * returned. 158 * 159 * @see FieldPosition 160 */ 161 public static final int INTEGER_FIELD = 0; 162 163 /** 164 * Field constant used to construct a FieldPosition object. Signifies that the position of the fraction part of a formatted number should be 165 * returned. 166 * 167 * @see FieldPosition 168 */ 169 public static final int FRACTION_FIELD = 1; 170 171 /** 172 * Formats an object to produce a string. This general routines allows polymorphic parsing and formatting for objects. 173 * 174 * @param number 175 * the object to format 176 * @param toAppendTo 177 * where the text is to be appended 178 * @param pos 179 * On input: an alignment field, if desired. On output: the offsets of the alignment field. 180 * @return the value passed in as toAppendTo (this allows chaining, as with StringBuffer.append()) 181 * @exception IllegalArgumentException 182 * when the Format cannot format the given object. 183 * @see FieldPosition 184 */ 185 public final StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) { 186 if (number instanceof Long) 187 return format(((Long) number).longValue(), toAppendTo, pos); 188 else if (number instanceof Double) 189 return format(((Double) number).doubleValue(), toAppendTo, pos); 190 else if (number instanceof Integer) 191 return format(((Integer) number).intValue(), toAppendTo, pos); 192 else { 193 throw new IllegalArgumentException("Cannot format given Object as a Number"); 194 } 195 } 196 197 /** 198 * Parses text from a string to produce a <code>Number</code>. 199 * <p> 200 * The method attempts to parse text starting at the index given by <code>pos</code>. If parsing succeeds, then the index of <code>pos</code> is 201 * updated to the index after the last character used (parsing does not necessarily use all characters up to the end of the string), and the parsed 202 * number is returned. The updated <code>pos</code> can be used to indicate the starting point for the next call to this method. If an error occurs, 203 * then the index of <code>pos</code> is not changed, the error index of <code>pos</code> is set to the index of the character where the error 204 * occurred, and null is returned. 205 * <p> 206 * See the {@link #parse(String, ParsePosition)} method for more information on number parsing. 207 * 208 * @param source 209 * A <code>String</code>, part of which should be parsed. 210 * @param pos 211 * A <code>ParsePosition</code> object with index and error index information as described above. 212 * @return A <code>Number</code> parsed from the string. In case of error, returns null. 213 * @exception NullPointerException 214 * if <code>pos</code> is null. 215 */ 216 // public final Object parseObject(String source, ParsePosition pos) { 217 // return parse(source, pos); 218 // } 219 /** 220 * Specialization of format. 221 * 222 * @see Format#format 223 */ 224 public final String format(double number) { 225 return format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE).toString(); 226 } 227 228 /** 229 * Specialization of format. 230 * 231 * @see Format#format 232 */ 233 public final String format(long number) { 234 return format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE).toString(); 235 } 236 237 /** 238 * Specialization of format. 239 * 240 * @see Format#format 241 */ 242 public abstract StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos); 243 244 /** 245 * Specialization of format. 246 * 247 * @see Format#format 248 */ 249 public abstract StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos); 250 251 // /** 252 // * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE, 253 // * Long.MAX_VALUE] and with no decimals), otherwise a Double. If 254 // IntegerOnly 255 // * is set, will stop at a decimal point (or equivalent; e.g., for rational 256 // * numbers "1 2/3", will stop after the 1). Does not throw an exception; 257 // if 258 // * no object can be parsed, index is unchanged! 259 // * 260 // * @see NumberFormat#isParseIntegerOnly 261 // * @see Format#parseObject 262 // */ 263 // public abstract Number parse(String source, ParsePosition parsePosition); 264 // 265 // /** 266 // * Parses text from the beginning of the given string to produce a number. 267 // * The method may not use the entire text of the given string. 268 // * <p> 269 // * See the {@link #parse(String, ParsePosition)} method for more 270 // information 271 // * on number parsing. 272 // * 273 // * @param source 274 // * A <code>String</code> whose beginning should be parsed. 275 // * @return A <code>Number</code> parsed from the string. 276 // * @exception ParseException 277 // * if the beginning of the specified string cannot be parsed. 278 // */ 279 // public Number parse(String source) throws ParseException { 280 // ParsePosition parsePosition = new ParsePosition(0); 281 // Number result = parse(source, parsePosition); 282 // if (parsePosition.index == 0) { 283 // throw new ParseException("Unparseable number: \"" + source + "\"", 284 // parsePosition.errorIndex); 285 // } 286 // return result; 287 // } 288 289 /** 290 * Returns true if this format will parse numbers as integers only. For example in the English locale, with ParseIntegerOnly true, the string 291 * "1234." would be parsed as the integer value 1234 and parsing would stop at the "." character. Of course, the exact format accepted by the parse 292 * operation is locale dependant and determined by sub-classes of NumberFormat. 293 */ 294 boolean isParseIntegerOnly() { 295 return parseIntegerOnly; 296 } 297 298 /** 299 * Sets whether or not numbers should be parsed as integers only. 300 * 301 * @see #isParseIntegerOnly 302 */ 303 void setParseIntegerOnly(boolean value) { 304 parseIntegerOnly = value; 305 } 306 307 // ============== Locale Stuff ===================== 308 309 /** 310 * Returns a general-purpose number format. 311 * 312 * @return the {@code NumberFormat} instance for general-purpose number formatting 313 */ 314 public static final NumberFormat getInstance() { 315 return getNumberInstance(); 316 } 317 318 /** 319 * Returns a general-purpose number format for the current default locale. 320 */ 321 public final static NumberFormat getNumberInstance() { 322 return getInstance(NUMBERSTYLE); 323 } 324 325 /** 326 * Returns an integer number format for the current default locale. The returned number format is configured to round floating point numbers to the 327 * nearest integer using IEEE half-even rounding (see {@link java.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting, and to parse 328 * only the integer part of an input string (see {@link #isParseIntegerOnly isParseIntegerOnly}). NOTE: <B>java.math.BigDecimal</B> is found in J2ME 329 * CDC profiles such as J2ME Foundation Profile. 330 * 331 * @return a number format for integer values 332 */ 333 public final static NumberFormat getIntegerInstance() { 334 return getInstance(INTEGERSTYLE); 335 } 336 337 /** 338 * Returns a currency format for the current default locale. 339 */ 340 public final static NumberFormat getCurrencyInstance() { 341 return getInstance(CURRENCYSTYLE); 342 } 343 344 /** 345 * Returns a percentage format for the current default locale. 346 */ 347 public final static NumberFormat getPercentInstance() { 348 return getInstance(PERCENTSTYLE); 349 } 350 351 /** 352 * Returns a scientific format for the current default locale. 353 */ 354 /* public */final static NumberFormat getScientificInstance() { 355 return getInstance(SCIENTIFICSTYLE); 356 } 357 358 /** 359 * Overrides hashCode 360 */ 361 public int hashCode() { 362 return maximumIntegerDigits * 37 + maxFractionDigits; 363 // just enough fields for a reasonable distribution 364 } 365 366 /** 367 * Overrides equals 368 */ 369 public boolean equals(Object obj) { 370 if (obj == null) 371 return false; 372 if (this == obj) 373 return true; 374 if (getClass() != obj.getClass()) 375 return false; 376 NumberFormat other = (NumberFormat) obj; 377 return (maximumIntegerDigits == other.maximumIntegerDigits && minimumIntegerDigits == other.minimumIntegerDigits 378 && maximumFractionDigits == other.maximumFractionDigits && minimumFractionDigits == other.minimumFractionDigits 379 && groupingUsed == other.groupingUsed && parseIntegerOnly == other.parseIntegerOnly); 380 } 381 382 /** 383 * Returns true if grouping is used in this format. For example, in the English locale, with grouping on, the number 1234567 might be formatted as 384 * "1,234,567". The grouping separator as well as the size of each group is locale dependant and is determined by sub-classes of NumberFormat. 385 * 386 * @see #setGroupingUsed 387 */ 388 boolean isGroupingUsed() { 389 return groupingUsed; 390 } 391 392 /** 393 * Set whether or not grouping will be used in this format. 394 * 395 * @see #isGroupingUsed 396 */ 397 void setGroupingUsed(boolean newValue) { 398 groupingUsed = newValue; 399 } 400 401 /** 402 * Returns the maximum number of digits allowed in the integer portion of a number. 403 * 404 * @see #setMaximumIntegerDigits 405 */ 406 public int getMaximumIntegerDigits() { 407 return maximumIntegerDigits; 408 } 409 410 /** 411 * Sets the maximum number of digits allowed in the integer portion of a number. maximumIntegerDigits must be >= minimumIntegerDigits. If the new 412 * value for maximumIntegerDigits is less than the current value of minimumIntegerDigits, then minimumIntegerDigits will also be set to the new 413 * value. 414 * 415 * @param newValue 416 * the maximum number of integer digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper limit 417 * to this value appropriate to the numeric type being formatted. 418 * @see #getMaximumIntegerDigits 419 */ 420 public void setMaximumIntegerDigits(int newValue) { 421 maximumIntegerDigits = Math.max(0, newValue); 422 if (minimumIntegerDigits > maximumIntegerDigits) 423 minimumIntegerDigits = maximumIntegerDigits; 424 } 425 426 /** 427 * Returns the minimum number of digits allowed in the integer portion of a number. 428 * 429 * @see #setMinimumIntegerDigits 430 */ 431 public int getMinimumIntegerDigits() { 432 return minimumIntegerDigits; 433 } 434 435 /** 436 * Sets the minimum number of digits allowed in the integer portion of a number. minimumIntegerDigits must be <= maximumIntegerDigits. If the new 437 * value for minimumIntegerDigits exceeds the current value of maximumIntegerDigits, then maximumIntegerDigits will also be set to the new value 438 * 439 * @param newValue 440 * the minimum number of integer digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper limit 441 * to this value appropriate to the numeric type being formatted. 442 * @see #getMinimumIntegerDigits 443 */ 444 public void setMinimumIntegerDigits(int newValue) { 445 minimumIntegerDigits = Math.max(0, newValue); 446 if (minimumIntegerDigits > maximumIntegerDigits) 447 maximumIntegerDigits = minimumIntegerDigits; 448 } 449 450 /** 451 * Returns the maximum number of digits allowed in the fraction portion of a number. 452 * 453 * @see #setMaximumFractionDigits 454 */ 455 public int getMaximumFractionDigits() { 456 return maximumFractionDigits; 457 } 458 459 /** 460 * Sets the maximum number of digits allowed in the fraction portion of a number. maximumFractionDigits must be >= minimumFractionDigits. If the new 461 * value for maximumFractionDigits is less than the current value of minimumFractionDigits, then minimumFractionDigits will also be set to the new 462 * value. 463 * 464 * @param newValue 465 * the maximum number of fraction digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper 466 * limit to this value appropriate to the numeric type being formatted. 467 * @see #getMaximumFractionDigits 468 */ 469 public void setMaximumFractionDigits(int newValue) { 470 maximumFractionDigits = Math.max(0, newValue); 471 if (maximumFractionDigits < minimumFractionDigits) 472 minimumFractionDigits = maximumFractionDigits; 473 } 474 475 /** 476 * Returns the minimum number of digits allowed in the fraction portion of a number. 477 * 478 * @see #setMinimumFractionDigits 479 */ 480 public int getMinimumFractionDigits() { 481 return minimumFractionDigits; 482 } 483 484 /** 485 * Sets the minimum number of digits allowed in the fraction portion of a number. minimumFractionDigits must be <= maximumFractionDigits. If the new 486 * value for minimumFractionDigits exceeds the current value of maximumFractionDigits, then maximumIntegerDigits will also be set to the new value 487 * 488 * @param newValue 489 * the minimum number of fraction digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper 490 * limit to this value appropriate to the numeric type being formatted. 491 * @see #getMinimumFractionDigits 492 */ 493 public void setMinimumFractionDigits(int newValue) { 494 minimumFractionDigits = Math.max(0, newValue); 495 if (maximumFractionDigits < minimumFractionDigits) 496 maximumFractionDigits = minimumFractionDigits; 497 } 498 499 // =======================privates=============================== 500 501 private static NumberFormat getInstance(int choice) { 502 /* try the cache first */ 503 String[] numberPatterns = new String[] { "", "", "", "", "" }; 504 505 DecimalFormatSymbols symbols = new DecimalFormatSymbols(); 506 int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice; 507 DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols); 508 509 if (choice == INTEGERSTYLE) { 510 format.setMaximumFractionDigits(0); 511 format.setDecimalSeparatorAlwaysShown(false); 512 format.setParseIntegerOnly(true); 513 } else if (choice == CURRENCYSTYLE) { 514 // format.adjustForCurrencyDefaultFractionDigits(); 515 } 516 517 return format; 518 } 519 520 // Constants used by factory methods to specify a style of format. 521 private static final int NUMBERSTYLE = 0; 522 private static final int CURRENCYSTYLE = 1; 523 private static final int PERCENTSTYLE = 2; 524 private static final int SCIENTIFICSTYLE = 3; 525 private static final int INTEGERSTYLE = 4; 526 527 /** 528 * True if the the grouping (i.e. thousands) separator is used when formatting and parsing numbers. 529 * 530 * @serial 531 * @see #isGroupingUsed 532 */ 533 private boolean groupingUsed = true; 534 535 /** 536 * The maximum number of digits allowed in the integer portion of a number. <code>maxIntegerDigits</code> must be greater than or equal to 537 * <code>minIntegerDigits</code>. 538 * <p> 539 * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 540 * <code>int</code> field <code>maximumIntegerDigits</code> is used instead. When writing to a stream, <code>maxIntegerDigits</code> is set to 541 * <code>maximumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if 542 * <code>serialVersionOnStream</code> is less than 1. 543 * 544 * @serial 545 * @see #getMaximumIntegerDigits 546 */ 547 private byte maxIntegerDigits = 40; 548 549 /** 550 * The minimum number of digits allowed in the integer portion of a number. <code>minimumIntegerDigits</code> must be less than or equal to 551 * <code>maximumIntegerDigits</code>. 552 * <p> 553 * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 554 * <code>int</code> field <code>minimumIntegerDigits</code> is used instead. When writing to a stream, <code>minIntegerDigits</code> is set to 555 * <code>minimumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if 556 * <code>serialVersionOnStream</code> is less than 1. 557 * 558 * @serial 559 * @see #getMinimumIntegerDigits 560 */ 561 private byte minIntegerDigits = 1; 562 563 /** 564 * The maximum number of digits allowed in the fractional portion of a number. <code>maximumFractionDigits</code> must be greater than or equal to 565 * <code>minimumFractionDigits</code>. 566 * <p> 567 * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 568 * <code>int</code> field <code>maximumFractionDigits</code> is used instead. When writing to a stream, <code>maxFractionDigits</code> is set to 569 * <code>maximumFractionDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if 570 * <code>serialVersionOnStream</code> is less than 1. 571 * 572 * @serial 573 * @see #getMaximumFractionDigits 574 */ 575 private byte maxFractionDigits = 3; // invariant, >= minFractionDigits 576 577 /** 578 * The minimum number of digits allowed in the fractional portion of a number. <code>minimumFractionDigits</code> must be less than or equal to 579 * <code>maximumFractionDigits</code>. 580 * <p> 581 * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new 582 * <code>int</code> field <code>minimumFractionDigits</code> is used instead. When writing to a stream, <code>minFractionDigits</code> is set to 583 * <code>minimumFractionDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if 584 * <code>serialVersionOnStream</code> is less than 1. 585 * 586 * @serial 587 * @see #getMinimumFractionDigits 588 */ 589 private byte minFractionDigits = 0; 590 591 /** 592 * True if this format will parse numbers as integers only. 593 * 594 * @serial 595 * @see #isParseIntegerOnly 596 */ 597 private boolean parseIntegerOnly = false; 598 599 // new fields for 1.2. byte is too small for integer digits. 600 601 /** 602 * The maximum number of digits allowed in the integer portion of a number. <code>maximumIntegerDigits</code> must be greater than or equal to 603 * <code>minimumIntegerDigits</code>. 604 * 605 * @serial 606 * @since 1.2 607 * @see #getMaximumIntegerDigits 608 */ 609 private int maximumIntegerDigits = 40; 610 611 /** 612 * The minimum number of digits allowed in the integer portion of a number. <code>minimumIntegerDigits</code> must be less than or equal to 613 * <code>maximumIntegerDigits</code>. 614 * 615 * @serial 616 * @since 1.2 617 * @see #getMinimumIntegerDigits 618 */ 619 private int minimumIntegerDigits = 1; 620 621 /** 622 * The maximum number of digits allowed in the fractional portion of a number. <code>maximumFractionDigits</code> must be greater than or equal to 623 * <code>minimumFractionDigits</code>. 624 * 625 * @serial 626 * @since 1.2 627 * @see #getMaximumFractionDigits 628 */ 629 private int maximumFractionDigits = 3; // invariant, >= minFractionDigits 630 631 /** 632 * The minimum number of digits allowed in the fractional portion of a number. <code>minimumFractionDigits</code> must be less than or equal to 633 * <code>maximumFractionDigits</code>. 634 * 635 * @serial 636 * @since 1.2 637 * @see #getMinimumFractionDigits 638 */ 639 private int minimumFractionDigits = 0; 640 641 static final int currentSerialVersion = 1; 642 643 /** 644 * Describes the version of <code>NumberFormat</code> present on the stream. Possible values are: 645 * <ul> 646 * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format. In this version, the <code>int</code> fields such as 647 * <code>maximumIntegerDigits</code> were not present, and the <code>byte</code> fields such as <code>maxIntegerDigits</code> are used instead. 648 * 649 * <li><b>1</b>: the 1.2 version of the stream format. The values of the <code>byte</code> fields such as <code>maxIntegerDigits</code> are ignored, 650 * and the <code>int</code> fields such as <code>maximumIntegerDigits</code> are used instead. 651 * </ul> 652 * When streaming out a <code>NumberFormat</code>, the most recent format (corresponding to the highest allowable <code>serialVersionOnStream</code> 653 * ) is always written. 654 * 655 * @serial 656 * @since 1.2 657 */ 658 private int serialVersionOnStream = currentSerialVersion; 659 660 // Removed "implements Cloneable" clause. Needs to update serialization 661 // ID for backward compatibility. 662 static final long serialVersionUID = -2308460125733713944L; 663 664 // 665 // class for AttributedCharacterIterator attributes 666 // 667 /** 668 * Defines constants that are used as attribute keys in the <code>AttributedCharacterIterator</code> returned from 669 * <code>NumberFormat.formatToCharacterIterator</code> and as field identifiers in <code>FieldPosition</code>. 670 * 671 * @since 1.4 672 */ 673 public static class Field extends Format.Field { 674 // table of all instances in this class, used by readResolve 675 @SuppressWarnings("rawtypes") 676 private static final Hashtable instanceMap = new Hashtable(11); 677 678 /** 679 * Creates a Field instance with the specified name. 680 * 681 * @param name 682 * Name of the attribute 683 */ 684 protected Field(String name) { 685 super(name); 686 if (this.getClass() == NumberFormat.Field.class) { 687 instanceMap.put(name, this); 688 } 689 } 690 691 /** 692 * Constant identifying the integer field. 693 */ 694 public static final Field INTEGER = new Field("integer"); 695 696 /** 697 * Constant identifying the fraction field. 698 */ 699 public static final Field FRACTION = new Field("fraction"); 700 701 /** 702 * Constant identifying the exponent field. 703 */ 704 public static final Field EXPONENT = new Field("exponent"); 705 706 /** 707 * Constant identifying the decimal separator field. 708 */ 709 public static final Field DECIMAL_SEPARATOR = new Field("decimal separator"); 710 711 /** 712 * Constant identifying the sign field. 713 */ 714 public static final Field SIGN = new Field("sign"); 715 716 /** 717 * Constant identifying the grouping separator field. 718 */ 719 public static final Field GROUPING_SEPARATOR = new Field("grouping separator"); 720 721 /** 722 * Constant identifying the exponent symbol field. 723 */ 724 public static final Field EXPONENT_SYMBOL = new Field("exponent symbol"); 725 726 /** 727 * Constant identifying the percent field. 728 */ 729 public static final Field PERCENT = new Field("percent"); 730 731 /** 732 * Constant identifying the permille field. 733 */ 734 public static final Field PERMILLE = new Field("per mille"); 735 736 /** 737 * Constant identifying the currency field. 738 */ 739 public static final Field CURRENCY = new Field("currency"); 740 741 /** 742 * Constant identifying the exponent sign field. 743 */ 744 public static final Field EXPONENT_SIGN = new Field("exponent sign"); 745 } 746}