37 */
38
39 package java.text;
40
41 import java.io.InvalidObjectException;
42 import java.io.IOException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.math.BigInteger;
46 import java.math.RoundingMode;
47 import java.text.spi.NumberFormatProvider;
48 import java.util.Currency;
49 import java.util.HashMap;
50 import java.util.Hashtable;
51 import java.util.Locale;
52 import java.util.Map;
53 import java.util.ResourceBundle;
54 import java.util.concurrent.atomic.AtomicInteger;
55 import java.util.concurrent.atomic.AtomicLong;
56 import java.util.spi.LocaleServiceProvider;
57 import sun.util.LocaleServiceProviderPool;
58 import sun.util.resources.LocaleData;
59
60 /**
61 * <code>NumberFormat</code> is the abstract base class for all number
62 * formats. This class provides the interface for formatting and parsing
63 * numbers. <code>NumberFormat</code> also provides methods for determining
64 * which locales have number formats, and what their names are.
65 *
66 * <p>
67 * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
68 * Your code can be completely independent of the locale conventions for
69 * decimal points, thousands-separators, or even the particular decimal
70 * digits used, or whether the number format is even decimal.
71 *
72 * <p>
73 * To format a number for the current Locale, use one of the factory
74 * class methods:
75 * <blockquote>
76 * <pre>
77 * myString = NumberFormat.getInstance().format(myNumber);
215 * and {@link java.lang.Number#doubleValue()} for all other types. It
216 * then calls
217 * {@link #format(long,java.lang.StringBuffer,java.text.FieldPosition)}
218 * or {@link #format(double,java.lang.StringBuffer,java.text.FieldPosition)}.
219 * This may result in loss of magnitude information and precision for
220 * <code>BigInteger</code> and <code>BigDecimal</code> values.
221 * @param number the number to format
222 * @param toAppendTo the <code>StringBuffer</code> to which the formatted
223 * text is to be appended
224 * @param pos On input: an alignment field, if desired.
225 * On output: the offsets of the alignment field.
226 * @return the value passed in as <code>toAppendTo</code>
227 * @exception IllegalArgumentException if <code>number</code> is
228 * null or not an instance of <code>Number</code>.
229 * @exception NullPointerException if <code>toAppendTo</code> or
230 * <code>pos</code> is null
231 * @exception ArithmeticException if rounding is needed with rounding
232 * mode being set to RoundingMode.UNNECESSARY
233 * @see java.text.FieldPosition
234 */
235 public StringBuffer format(Object number,
236 StringBuffer toAppendTo,
237 FieldPosition pos) {
238 if (number instanceof Long || number instanceof Integer ||
239 number instanceof Short || number instanceof Byte ||
240 number instanceof AtomicInteger || number instanceof AtomicLong ||
241 (number instanceof BigInteger &&
242 ((BigInteger)number).bitLength() < 64)) {
243 return format(((Number)number).longValue(), toAppendTo, pos);
244 } else if (number instanceof Number) {
245 return format(((Number)number).doubleValue(), toAppendTo, pos);
246 } else {
247 throw new IllegalArgumentException("Cannot format given Object as a Number");
248 }
249 }
250
251 /**
252 * Parses text from a string to produce a <code>Number</code>.
253 * <p>
254 * The method attempts to parse text starting at the index given by
255 * <code>pos</code>.
256 * If parsing succeeds, then the index of <code>pos</code> is updated
257 * to the index after the last character used (parsing does not necessarily
258 * use all characters up to the end of the string), and the parsed
259 * number is returned. The updated <code>pos</code> can be used to
260 * indicate the starting point for the next call to this method.
261 * If an error occurs, then the index of <code>pos</code> is not
262 * changed, the error index of <code>pos</code> is set to the index of
263 * the character where the error occurred, and null is returned.
264 * <p>
265 * See the {@link #parse(String, ParsePosition)} method for more information
266 * on number parsing.
267 *
268 * @param source A <code>String</code>, part of which should be parsed.
269 * @param pos A <code>ParsePosition</code> object with index and error
270 * index information as described above.
271 * @return A <code>Number</code> parsed from the string. In case of
272 * error, returns null.
273 * @exception NullPointerException if <code>pos</code> is null.
274 */
275 public final Object parseObject(String source, ParsePosition pos) {
276 return parse(source, pos);
277 }
278
279 /**
280 * Specialization of format.
281 * @exception ArithmeticException if rounding is needed with rounding
282 * mode being set to RoundingMode.UNNECESSARY
283 * @see java.text.Format#format
284 */
285 public final String format(double number) {
286 return format(number, new StringBuffer(),
287 DontCareFieldPosition.INSTANCE).toString();
288 }
289
290 /**
291 * Specialization of format.
292 * @exception ArithmeticException if rounding is needed with rounding
293 * mode being set to RoundingMode.UNNECESSARY
294 * @see java.text.Format#format
484 /**
485 * Returns an array of all locales for which the
486 * <code>get*Instance</code> methods of this class can return
487 * localized instances.
488 * The returned array represents the union of locales supported by the Java
489 * runtime and by installed
490 * {@link java.text.spi.NumberFormatProvider NumberFormatProvider} implementations.
491 * It must contain at least a <code>Locale</code> instance equal to
492 * {@link java.util.Locale#US Locale.US}.
493 *
494 * @return An array of locales for which localized
495 * <code>NumberFormat</code> instances are available.
496 */
497 public static Locale[] getAvailableLocales() {
498 LocaleServiceProviderPool pool =
499 LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
500 return pool.getAvailableLocales();
501 }
502
503 /**
504 * Overrides hashCode
505 */
506 public int hashCode() {
507 return maximumIntegerDigits * 37 + maxFractionDigits;
508 // just enough fields for a reasonable distribution
509 }
510
511 /**
512 * Overrides equals
513 */
514 public boolean equals(Object obj) {
515 if (obj == null) {
516 return false;
517 }
518 if (this == obj) {
519 return true;
520 }
521 if (getClass() != obj.getClass()) {
522 return false;
523 }
524 NumberFormat other = (NumberFormat) obj;
525 return (maximumIntegerDigits == other.maximumIntegerDigits
526 && minimumIntegerDigits == other.minimumIntegerDigits
527 && maximumFractionDigits == other.maximumFractionDigits
528 && minimumFractionDigits == other.minimumFractionDigits
529 && groupingUsed == other.groupingUsed
530 && parseIntegerOnly == other.parseIntegerOnly);
531 }
532
533 /**
534 * Overrides Cloneable
535 */
536 public Object clone() {
537 NumberFormat other = (NumberFormat) super.clone();
538 return other;
539 }
540
541 /**
542 * Returns true if grouping is used in this format. For example, in the
543 * English locale, with grouping on, the number 1234567 might be formatted
544 * as "1,234,567". The grouping separator as well as the size of each group
545 * is locale dependant and is determined by sub-classes of NumberFormat.
546 * @see #setGroupingUsed
547 */
548 public boolean isGroupingUsed() {
549 return groupingUsed;
550 }
551
552 /**
553 * Set whether or not grouping will be used in this format.
554 * @see #isGroupingUsed
555 */
724 * The default implementation of this method in NumberFormat always
725 * throws {@link java.lang.UnsupportedOperationException}.
726 * Subclasses which handle different rounding modes should override
727 * this method.
728 *
729 * @exception UnsupportedOperationException The default implementation
730 * always throws this exception
731 * @exception NullPointerException if <code>roundingMode</code> is null
732 * @param roundingMode The <code>RoundingMode</code> to be used
733 * @see #getRoundingMode()
734 * @since 1.6
735 */
736 public void setRoundingMode(RoundingMode roundingMode) {
737 throw new UnsupportedOperationException();
738 }
739
740 // =======================privates===============================
741
742 private static NumberFormat getInstance(Locale desiredLocale,
743 int choice) {
744 // Check whether a provider can provide an implementation that's closer
745 // to the requested locale than what the Java runtime itself can provide.
746 LocaleServiceProviderPool pool =
747 LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
748 if (pool.hasProviders()) {
749 NumberFormat providersInstance = pool.getLocalizedObject(
750 NumberFormatGetter.INSTANCE,
751 desiredLocale,
752 choice);
753 if (providersInstance != null) {
754 return providersInstance;
755 }
756 }
757
758 /* try the cache first */
759 String[] numberPatterns = cachedLocaleData.get(desiredLocale);
760 if (numberPatterns == null) { /* cache miss */
761 ResourceBundle resource = LocaleData.getNumberFormatData(desiredLocale);
762 numberPatterns = resource.getStringArray("NumberPatterns");
763 /* update cache */
764 cachedLocaleData.put(desiredLocale, numberPatterns);
765 }
766
767 DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale);
768 int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
769 DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
770
771 if (choice == INTEGERSTYLE) {
772 format.setMaximumFractionDigits(0);
773 format.setDecimalSeparatorAlwaysShown(false);
774 format.setParseIntegerOnly(true);
775 } else if (choice == CURRENCYSTYLE) {
776 format.adjustForCurrencyDefaultFractionDigits();
777 }
778
779 return format;
780 }
781
782 /**
783 * First, read in the default serializable data.
784 *
785 * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
786 * the stream was written by JDK 1.1,
787 * set the <code>int</code> fields such as <code>maximumIntegerDigits</code>
788 * to be equal to the <code>byte</code> fields such as <code>maxIntegerDigits</code>,
789 * since the <code>int</code> fields were not present in JDK 1.1.
790 * Finally, set serialVersionOnStream back to the maximum allowed value so that
791 * default serialization will work properly if this object is streamed out again.
792 *
793 * <p>If <code>minimumIntegerDigits</code> is greater than
794 * <code>maximumIntegerDigits</code> or <code>minimumFractionDigits</code>
795 * is greater than <code>maximumFractionDigits</code>, then the stream data
796 * is invalid and this method throws an <code>InvalidObjectException</code>.
797 * In addition, if any of these values is negative, then this method throws
798 * an <code>InvalidObjectException</code>.
799 *
800 * @since 1.2
801 */
824 * equal to the <code>int</code> fields such as <code>maximumIntegerDigits</code>
825 * (or to <code>Byte.MAX_VALUE</code>, whichever is smaller), for compatibility
826 * with the JDK 1.1 version of the stream format.
827 *
828 * @since 1.2
829 */
830 private void writeObject(ObjectOutputStream stream)
831 throws IOException
832 {
833 maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ?
834 Byte.MAX_VALUE : (byte)maximumIntegerDigits;
835 minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ?
836 Byte.MAX_VALUE : (byte)minimumIntegerDigits;
837 maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ?
838 Byte.MAX_VALUE : (byte)maximumFractionDigits;
839 minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ?
840 Byte.MAX_VALUE : (byte)minimumFractionDigits;
841 stream.defaultWriteObject();
842 }
843
844 /**
845 * Cache to hold the NumberPatterns of a Locale.
846 */
847 private static final Hashtable<Locale, String[]> cachedLocaleData = new Hashtable<>(3);
848
849 // Constants used by factory methods to specify a style of format.
850 private static final int NUMBERSTYLE = 0;
851 private static final int CURRENCYSTYLE = 1;
852 private static final int PERCENTSTYLE = 2;
853 private static final int SCIENTIFICSTYLE = 3;
854 private static final int INTEGERSTYLE = 4;
855
856 /**
857 * True if the grouping (i.e. thousands) separator is used when
858 * formatting and parsing numbers.
859 *
860 * @serial
861 * @see #isGroupingUsed
862 */
863 private boolean groupingUsed = true;
864
865 /**
866 * The maximum number of digits allowed in the integer portion of a
867 * number. <code>maxIntegerDigits</code> must be greater than or equal to
868 * <code>minIntegerDigits</code>.
1039
1040 /**
1041 * Creates a Field instance with the specified
1042 * name.
1043 *
1044 * @param name Name of the attribute
1045 */
1046 protected Field(String name) {
1047 super(name);
1048 if (this.getClass() == NumberFormat.Field.class) {
1049 instanceMap.put(name, this);
1050 }
1051 }
1052
1053 /**
1054 * Resolves instances being deserialized to the predefined constants.
1055 *
1056 * @throws InvalidObjectException if the constant could not be resolved.
1057 * @return resolved NumberFormat.Field constant
1058 */
1059 protected Object readResolve() throws InvalidObjectException {
1060 if (this.getClass() != NumberFormat.Field.class) {
1061 throw new InvalidObjectException("subclass didn't correctly implement readResolve");
1062 }
1063
1064 Object instance = instanceMap.get(getName());
1065 if (instance != null) {
1066 return instance;
1067 } else {
1068 throw new InvalidObjectException("unknown attribute name");
1069 }
1070 }
1071
1072 /**
1073 * Constant identifying the integer field.
1074 */
1075 public static final Field INTEGER = new Field("integer");
1076
1077 /**
1078 * Constant identifying the fraction field.
1110 /**
1111 * Constant identifying the percent field.
1112 */
1113 public static final Field PERCENT = new Field("percent");
1114
1115 /**
1116 * Constant identifying the permille field.
1117 */
1118 public static final Field PERMILLE = new Field("per mille");
1119
1120 /**
1121 * Constant identifying the currency field.
1122 */
1123 public static final Field CURRENCY = new Field("currency");
1124
1125 /**
1126 * Constant identifying the exponent sign field.
1127 */
1128 public static final Field EXPONENT_SIGN = new Field("exponent sign");
1129 }
1130
1131 /**
1132 * Obtains a NumberFormat instance from a NumberFormatProvider implementation.
1133 */
1134 private static class NumberFormatGetter
1135 implements LocaleServiceProviderPool.LocalizedObjectGetter<NumberFormatProvider,
1136 NumberFormat> {
1137 private static final NumberFormatGetter INSTANCE = new NumberFormatGetter();
1138
1139 public NumberFormat getObject(NumberFormatProvider numberFormatProvider,
1140 Locale locale,
1141 String key,
1142 Object... params) {
1143 assert params.length == 1;
1144 int choice = (Integer)params[0];
1145
1146 switch (choice) {
1147 case NUMBERSTYLE:
1148 return numberFormatProvider.getNumberInstance(locale);
1149 case PERCENTSTYLE:
1150 return numberFormatProvider.getPercentInstance(locale);
1151 case CURRENCYSTYLE:
1152 return numberFormatProvider.getCurrencyInstance(locale);
1153 case INTEGERSTYLE:
1154 return numberFormatProvider.getIntegerInstance(locale);
1155 default:
1156 assert false : choice;
1157 }
1158
1159 return null;
1160 }
1161 }
1162 }
|
37 */
38
39 package java.text;
40
41 import java.io.InvalidObjectException;
42 import java.io.IOException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.math.BigInteger;
46 import java.math.RoundingMode;
47 import java.text.spi.NumberFormatProvider;
48 import java.util.Currency;
49 import java.util.HashMap;
50 import java.util.Hashtable;
51 import java.util.Locale;
52 import java.util.Map;
53 import java.util.ResourceBundle;
54 import java.util.concurrent.atomic.AtomicInteger;
55 import java.util.concurrent.atomic.AtomicLong;
56 import java.util.spi.LocaleServiceProvider;
57 import sun.util.locale.provider.LocaleProviderAdapter;
58 import sun.util.locale.provider.LocaleServiceProviderPool;
59 import sun.util.resources.LocaleData;
60
61 /**
62 * <code>NumberFormat</code> is the abstract base class for all number
63 * formats. This class provides the interface for formatting and parsing
64 * numbers. <code>NumberFormat</code> also provides methods for determining
65 * which locales have number formats, and what their names are.
66 *
67 * <p>
68 * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
69 * Your code can be completely independent of the locale conventions for
70 * decimal points, thousands-separators, or even the particular decimal
71 * digits used, or whether the number format is even decimal.
72 *
73 * <p>
74 * To format a number for the current Locale, use one of the factory
75 * class methods:
76 * <blockquote>
77 * <pre>
78 * myString = NumberFormat.getInstance().format(myNumber);
216 * and {@link java.lang.Number#doubleValue()} for all other types. It
217 * then calls
218 * {@link #format(long,java.lang.StringBuffer,java.text.FieldPosition)}
219 * or {@link #format(double,java.lang.StringBuffer,java.text.FieldPosition)}.
220 * This may result in loss of magnitude information and precision for
221 * <code>BigInteger</code> and <code>BigDecimal</code> values.
222 * @param number the number to format
223 * @param toAppendTo the <code>StringBuffer</code> to which the formatted
224 * text is to be appended
225 * @param pos On input: an alignment field, if desired.
226 * On output: the offsets of the alignment field.
227 * @return the value passed in as <code>toAppendTo</code>
228 * @exception IllegalArgumentException if <code>number</code> is
229 * null or not an instance of <code>Number</code>.
230 * @exception NullPointerException if <code>toAppendTo</code> or
231 * <code>pos</code> is null
232 * @exception ArithmeticException if rounding is needed with rounding
233 * mode being set to RoundingMode.UNNECESSARY
234 * @see java.text.FieldPosition
235 */
236 @Override
237 public StringBuffer format(Object number,
238 StringBuffer toAppendTo,
239 FieldPosition pos) {
240 if (number instanceof Long || number instanceof Integer ||
241 number instanceof Short || number instanceof Byte ||
242 number instanceof AtomicInteger || number instanceof AtomicLong ||
243 (number instanceof BigInteger &&
244 ((BigInteger)number).bitLength() < 64)) {
245 return format(((Number)number).longValue(), toAppendTo, pos);
246 } else if (number instanceof Number) {
247 return format(((Number)number).doubleValue(), toAppendTo, pos);
248 } else {
249 throw new IllegalArgumentException("Cannot format given Object as a Number");
250 }
251 }
252
253 /**
254 * Parses text from a string to produce a <code>Number</code>.
255 * <p>
256 * The method attempts to parse text starting at the index given by
257 * <code>pos</code>.
258 * If parsing succeeds, then the index of <code>pos</code> is updated
259 * to the index after the last character used (parsing does not necessarily
260 * use all characters up to the end of the string), and the parsed
261 * number is returned. The updated <code>pos</code> can be used to
262 * indicate the starting point for the next call to this method.
263 * If an error occurs, then the index of <code>pos</code> is not
264 * changed, the error index of <code>pos</code> is set to the index of
265 * the character where the error occurred, and null is returned.
266 * <p>
267 * See the {@link #parse(String, ParsePosition)} method for more information
268 * on number parsing.
269 *
270 * @param source A <code>String</code>, part of which should be parsed.
271 * @param pos A <code>ParsePosition</code> object with index and error
272 * index information as described above.
273 * @return A <code>Number</code> parsed from the string. In case of
274 * error, returns null.
275 * @exception NullPointerException if <code>pos</code> is null.
276 */
277 @Override
278 public final Object parseObject(String source, ParsePosition pos) {
279 return parse(source, pos);
280 }
281
282 /**
283 * Specialization of format.
284 * @exception ArithmeticException if rounding is needed with rounding
285 * mode being set to RoundingMode.UNNECESSARY
286 * @see java.text.Format#format
287 */
288 public final String format(double number) {
289 return format(number, new StringBuffer(),
290 DontCareFieldPosition.INSTANCE).toString();
291 }
292
293 /**
294 * Specialization of format.
295 * @exception ArithmeticException if rounding is needed with rounding
296 * mode being set to RoundingMode.UNNECESSARY
297 * @see java.text.Format#format
487 /**
488 * Returns an array of all locales for which the
489 * <code>get*Instance</code> methods of this class can return
490 * localized instances.
491 * The returned array represents the union of locales supported by the Java
492 * runtime and by installed
493 * {@link java.text.spi.NumberFormatProvider NumberFormatProvider} implementations.
494 * It must contain at least a <code>Locale</code> instance equal to
495 * {@link java.util.Locale#US Locale.US}.
496 *
497 * @return An array of locales for which localized
498 * <code>NumberFormat</code> instances are available.
499 */
500 public static Locale[] getAvailableLocales() {
501 LocaleServiceProviderPool pool =
502 LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
503 return pool.getAvailableLocales();
504 }
505
506 /**
507 * Overrides hashCode.
508 */
509 @Override
510 public int hashCode() {
511 return maximumIntegerDigits * 37 + maxFractionDigits;
512 // just enough fields for a reasonable distribution
513 }
514
515 /**
516 * Overrides equals.
517 */
518 @Override
519 public boolean equals(Object obj) {
520 if (obj == null) {
521 return false;
522 }
523 if (this == obj) {
524 return true;
525 }
526 if (getClass() != obj.getClass()) {
527 return false;
528 }
529 NumberFormat other = (NumberFormat) obj;
530 return (maximumIntegerDigits == other.maximumIntegerDigits
531 && minimumIntegerDigits == other.minimumIntegerDigits
532 && maximumFractionDigits == other.maximumFractionDigits
533 && minimumFractionDigits == other.minimumFractionDigits
534 && groupingUsed == other.groupingUsed
535 && parseIntegerOnly == other.parseIntegerOnly);
536 }
537
538 /**
539 * Overrides Cloneable.
540 */
541 @Override
542 public Object clone() {
543 NumberFormat other = (NumberFormat) super.clone();
544 return other;
545 }
546
547 /**
548 * Returns true if grouping is used in this format. For example, in the
549 * English locale, with grouping on, the number 1234567 might be formatted
550 * as "1,234,567". The grouping separator as well as the size of each group
551 * is locale dependant and is determined by sub-classes of NumberFormat.
552 * @see #setGroupingUsed
553 */
554 public boolean isGroupingUsed() {
555 return groupingUsed;
556 }
557
558 /**
559 * Set whether or not grouping will be used in this format.
560 * @see #isGroupingUsed
561 */
730 * The default implementation of this method in NumberFormat always
731 * throws {@link java.lang.UnsupportedOperationException}.
732 * Subclasses which handle different rounding modes should override
733 * this method.
734 *
735 * @exception UnsupportedOperationException The default implementation
736 * always throws this exception
737 * @exception NullPointerException if <code>roundingMode</code> is null
738 * @param roundingMode The <code>RoundingMode</code> to be used
739 * @see #getRoundingMode()
740 * @since 1.6
741 */
742 public void setRoundingMode(RoundingMode roundingMode) {
743 throw new UnsupportedOperationException();
744 }
745
746 // =======================privates===============================
747
748 private static NumberFormat getInstance(Locale desiredLocale,
749 int choice) {
750 LocaleProviderAdapter adapter;
751 adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class,
752 desiredLocale);
753 NumberFormat numberFormat = getInstance(adapter, desiredLocale, choice);
754 if (numberFormat == null) {
755 numberFormat = getInstance(LocaleProviderAdapter.forJRE(),
756 desiredLocale, choice);
757 }
758 return numberFormat;
759 }
760
761 private static NumberFormat getInstance(LocaleProviderAdapter adapter,
762 Locale locale, int choice) {
763 NumberFormatProvider provider = adapter.getNumberFormatProvider();
764 NumberFormat numberFormat = null;
765 switch (choice) {
766 case NUMBERSTYLE:
767 numberFormat = provider.getNumberInstance(locale);
768 break;
769 case PERCENTSTYLE:
770 numberFormat = provider.getPercentInstance(locale);
771 break;
772 case CURRENCYSTYLE:
773 numberFormat = provider.getCurrencyInstance(locale);
774 break;
775 case INTEGERSTYLE:
776 numberFormat = provider.getIntegerInstance(locale);
777 break;
778 }
779 return numberFormat;
780 }
781
782 /**
783 * First, read in the default serializable data.
784 *
785 * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
786 * the stream was written by JDK 1.1,
787 * set the <code>int</code> fields such as <code>maximumIntegerDigits</code>
788 * to be equal to the <code>byte</code> fields such as <code>maxIntegerDigits</code>,
789 * since the <code>int</code> fields were not present in JDK 1.1.
790 * Finally, set serialVersionOnStream back to the maximum allowed value so that
791 * default serialization will work properly if this object is streamed out again.
792 *
793 * <p>If <code>minimumIntegerDigits</code> is greater than
794 * <code>maximumIntegerDigits</code> or <code>minimumFractionDigits</code>
795 * is greater than <code>maximumFractionDigits</code>, then the stream data
796 * is invalid and this method throws an <code>InvalidObjectException</code>.
797 * In addition, if any of these values is negative, then this method throws
798 * an <code>InvalidObjectException</code>.
799 *
800 * @since 1.2
801 */
824 * equal to the <code>int</code> fields such as <code>maximumIntegerDigits</code>
825 * (or to <code>Byte.MAX_VALUE</code>, whichever is smaller), for compatibility
826 * with the JDK 1.1 version of the stream format.
827 *
828 * @since 1.2
829 */
830 private void writeObject(ObjectOutputStream stream)
831 throws IOException
832 {
833 maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ?
834 Byte.MAX_VALUE : (byte)maximumIntegerDigits;
835 minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ?
836 Byte.MAX_VALUE : (byte)minimumIntegerDigits;
837 maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ?
838 Byte.MAX_VALUE : (byte)maximumFractionDigits;
839 minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ?
840 Byte.MAX_VALUE : (byte)minimumFractionDigits;
841 stream.defaultWriteObject();
842 }
843
844 // Constants used by factory methods to specify a style of format.
845 private static final int NUMBERSTYLE = 0;
846 private static final int CURRENCYSTYLE = 1;
847 private static final int PERCENTSTYLE = 2;
848 private static final int SCIENTIFICSTYLE = 3;
849 private static final int INTEGERSTYLE = 4;
850
851 /**
852 * True if the grouping (i.e. thousands) separator is used when
853 * formatting and parsing numbers.
854 *
855 * @serial
856 * @see #isGroupingUsed
857 */
858 private boolean groupingUsed = true;
859
860 /**
861 * The maximum number of digits allowed in the integer portion of a
862 * number. <code>maxIntegerDigits</code> must be greater than or equal to
863 * <code>minIntegerDigits</code>.
1034
1035 /**
1036 * Creates a Field instance with the specified
1037 * name.
1038 *
1039 * @param name Name of the attribute
1040 */
1041 protected Field(String name) {
1042 super(name);
1043 if (this.getClass() == NumberFormat.Field.class) {
1044 instanceMap.put(name, this);
1045 }
1046 }
1047
1048 /**
1049 * Resolves instances being deserialized to the predefined constants.
1050 *
1051 * @throws InvalidObjectException if the constant could not be resolved.
1052 * @return resolved NumberFormat.Field constant
1053 */
1054 @Override
1055 protected Object readResolve() throws InvalidObjectException {
1056 if (this.getClass() != NumberFormat.Field.class) {
1057 throw new InvalidObjectException("subclass didn't correctly implement readResolve");
1058 }
1059
1060 Object instance = instanceMap.get(getName());
1061 if (instance != null) {
1062 return instance;
1063 } else {
1064 throw new InvalidObjectException("unknown attribute name");
1065 }
1066 }
1067
1068 /**
1069 * Constant identifying the integer field.
1070 */
1071 public static final Field INTEGER = new Field("integer");
1072
1073 /**
1074 * Constant identifying the fraction field.
1106 /**
1107 * Constant identifying the percent field.
1108 */
1109 public static final Field PERCENT = new Field("percent");
1110
1111 /**
1112 * Constant identifying the permille field.
1113 */
1114 public static final Field PERMILLE = new Field("per mille");
1115
1116 /**
1117 * Constant identifying the currency field.
1118 */
1119 public static final Field CURRENCY = new Field("currency");
1120
1121 /**
1122 * Constant identifying the exponent sign field.
1123 */
1124 public static final Field EXPONENT_SIGN = new Field("exponent sign");
1125 }
1126 }
|