Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/text/DecimalFormatSymbols.java
38829 views
/*1* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved27* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved28*29* The original version of this source code and documentation is copyrighted30* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These31* materials are provided under terms of a License Agreement between Taligent32* and Sun. This technology is protected by multiple US and International33* patents. This notice and attribution to Taligent may not be removed.34* Taligent is a registered trademark of Taligent, Inc.35*36*/3738package java.text;3940import java.io.IOException;41import java.io.ObjectInputStream;42import java.io.Serializable;43import java.text.spi.DecimalFormatSymbolsProvider;44import java.util.ArrayList;45import java.util.Currency;46import java.util.List;47import java.util.Locale;48import java.util.MissingResourceException;49import java.util.ResourceBundle;50import java.util.concurrent.ConcurrentHashMap;51import java.util.concurrent.ConcurrentMap;52import sun.util.locale.provider.LocaleProviderAdapter;53import sun.util.locale.provider.LocaleServiceProviderPool;54import sun.util.locale.provider.ResourceBundleBasedAdapter;5556/**57* This class represents the set of symbols (such as the decimal separator,58* the grouping separator, and so on) needed by <code>DecimalFormat</code>59* to format numbers. <code>DecimalFormat</code> creates for itself an instance of60* <code>DecimalFormatSymbols</code> from its locale data. If you need to change any61* of these symbols, you can get the <code>DecimalFormatSymbols</code> object from62* your <code>DecimalFormat</code> and modify it.63*64* @see java.util.Locale65* @see DecimalFormat66* @author Mark Davis67* @author Alan Liu68*/6970public class DecimalFormatSymbols implements Cloneable, Serializable {7172/**73* Create a DecimalFormatSymbols object for the default74* {@link java.util.Locale.Category#FORMAT FORMAT} locale.75* This constructor can only construct instances for the locales76* supported by the Java runtime environment, not for those77* supported by installed78* {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}79* implementations. For full locale coverage, use the80* {@link #getInstance(Locale) getInstance} method.81* <p>This is equivalent to calling82* {@link #DecimalFormatSymbols(Locale)83* DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT))}.84* @see java.util.Locale#getDefault(java.util.Locale.Category)85* @see java.util.Locale.Category#FORMAT86*/87public DecimalFormatSymbols() {88initialize( Locale.getDefault(Locale.Category.FORMAT) );89}9091/**92* Create a DecimalFormatSymbols object for the given locale.93* This constructor can only construct instances for the locales94* supported by the Java runtime environment, not for those95* supported by installed96* {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}97* implementations. For full locale coverage, use the98* {@link #getInstance(Locale) getInstance} method.99* If the specified locale contains the {@link java.util.Locale#UNICODE_LOCALE_EXTENSION}100* for the numbering system, the instance is initialized with the specified numbering101* system if the JRE implementation supports it. For example,102* <pre>103* NumberFormat.getNumberInstance(Locale.forLanguageTag("th-TH-u-nu-thai"))104* </pre>105* This may return a {@code NumberFormat} instance with the Thai numbering system,106* instead of the Latin numbering system.107*108* @param locale the desired locale109* @exception NullPointerException if <code>locale</code> is null110*/111public DecimalFormatSymbols( Locale locale ) {112initialize( locale );113}114115/**116* Returns an array of all locales for which the117* <code>getInstance</code> methods of this class can return118* localized instances.119* The returned array represents the union of locales supported by the Java120* runtime and by installed121* {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}122* implementations. It must contain at least a <code>Locale</code>123* instance equal to {@link java.util.Locale#US Locale.US}.124*125* @return an array of locales for which localized126* <code>DecimalFormatSymbols</code> instances are available.127* @since 1.6128*/129public static Locale[] getAvailableLocales() {130LocaleServiceProviderPool pool =131LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class);132return pool.getAvailableLocales();133}134135/**136* Gets the <code>DecimalFormatSymbols</code> instance for the default137* locale. This method provides access to <code>DecimalFormatSymbols</code>138* instances for locales supported by the Java runtime itself as well139* as for those supported by installed140* {@link java.text.spi.DecimalFormatSymbolsProvider141* DecimalFormatSymbolsProvider} implementations.142* <p>This is equivalent to calling143* {@link #getInstance(Locale)144* getInstance(Locale.getDefault(Locale.Category.FORMAT))}.145* @see java.util.Locale#getDefault(java.util.Locale.Category)146* @see java.util.Locale.Category#FORMAT147* @return a <code>DecimalFormatSymbols</code> instance.148* @since 1.6149*/150public static final DecimalFormatSymbols getInstance() {151return getInstance(Locale.getDefault(Locale.Category.FORMAT));152}153154/**155* Gets the <code>DecimalFormatSymbols</code> instance for the specified156* locale. This method provides access to <code>DecimalFormatSymbols</code>157* instances for locales supported by the Java runtime itself as well158* as for those supported by installed159* {@link java.text.spi.DecimalFormatSymbolsProvider160* DecimalFormatSymbolsProvider} implementations.161* If the specified locale contains the {@link java.util.Locale#UNICODE_LOCALE_EXTENSION}162* for the numbering system, the instance is initialized with the specified numbering163* system if the JRE implementation supports it. For example,164* <pre>165* NumberFormat.getNumberInstance(Locale.forLanguageTag("th-TH-u-nu-thai"))166* </pre>167* This may return a {@code NumberFormat} instance with the Thai numbering system,168* instead of the Latin numbering system.169*170* @param locale the desired locale.171* @return a <code>DecimalFormatSymbols</code> instance.172* @exception NullPointerException if <code>locale</code> is null173* @since 1.6174*/175public static final DecimalFormatSymbols getInstance(Locale locale) {176LocaleProviderAdapter adapter;177adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);178DecimalFormatSymbolsProvider provider = adapter.getDecimalFormatSymbolsProvider();179DecimalFormatSymbols dfsyms = provider.getInstance(locale);180if (dfsyms == null) {181provider = LocaleProviderAdapter.forJRE().getDecimalFormatSymbolsProvider();182dfsyms = provider.getInstance(locale);183}184return dfsyms;185}186187/**188* Gets the character used for zero. Different for Arabic, etc.189*190* @return the character used for zero191*/192public char getZeroDigit() {193return zeroDigit;194}195196/**197* Sets the character used for zero. Different for Arabic, etc.198*199* @param zeroDigit the character used for zero200*/201public void setZeroDigit(char zeroDigit) {202this.zeroDigit = zeroDigit;203}204205/**206* Gets the character used for thousands separator. Different for French, etc.207*208* @return the grouping separator209*/210public char getGroupingSeparator() {211return groupingSeparator;212}213214/**215* Sets the character used for thousands separator. Different for French, etc.216*217* @param groupingSeparator the grouping separator218*/219public void setGroupingSeparator(char groupingSeparator) {220this.groupingSeparator = groupingSeparator;221}222223/**224* Gets the character used for decimal sign. Different for French, etc.225*226* @return the character used for decimal sign227*/228public char getDecimalSeparator() {229return decimalSeparator;230}231232/**233* Sets the character used for decimal sign. Different for French, etc.234*235* @param decimalSeparator the character used for decimal sign236*/237public void setDecimalSeparator(char decimalSeparator) {238this.decimalSeparator = decimalSeparator;239}240241/**242* Gets the character used for per mille sign. Different for Arabic, etc.243*244* @return the character used for per mille sign245*/246public char getPerMill() {247return perMill;248}249250/**251* Sets the character used for per mille sign. Different for Arabic, etc.252*253* @param perMill the character used for per mille sign254*/255public void setPerMill(char perMill) {256this.perMill = perMill;257}258259/**260* Gets the character used for percent sign. Different for Arabic, etc.261*262* @return the character used for percent sign263*/264public char getPercent() {265return percent;266}267268/**269* Sets the character used for percent sign. Different for Arabic, etc.270*271* @param percent the character used for percent sign272*/273public void setPercent(char percent) {274this.percent = percent;275}276277/**278* Gets the character used for a digit in a pattern.279*280* @return the character used for a digit in a pattern281*/282public char getDigit() {283return digit;284}285286/**287* Sets the character used for a digit in a pattern.288*289* @param digit the character used for a digit in a pattern290*/291public void setDigit(char digit) {292this.digit = digit;293}294295/**296* Gets the character used to separate positive and negative subpatterns297* in a pattern.298*299* @return the pattern separator300*/301public char getPatternSeparator() {302return patternSeparator;303}304305/**306* Sets the character used to separate positive and negative subpatterns307* in a pattern.308*309* @param patternSeparator the pattern separator310*/311public void setPatternSeparator(char patternSeparator) {312this.patternSeparator = patternSeparator;313}314315/**316* Gets the string used to represent infinity. Almost always left317* unchanged.318*319* @return the string representing infinity320*/321public String getInfinity() {322return infinity;323}324325/**326* Sets the string used to represent infinity. Almost always left327* unchanged.328*329* @param infinity the string representing infinity330*/331public void setInfinity(String infinity) {332this.infinity = infinity;333}334335/**336* Gets the string used to represent "not a number". Almost always left337* unchanged.338*339* @return the string representing "not a number"340*/341public String getNaN() {342return NaN;343}344345/**346* Sets the string used to represent "not a number". Almost always left347* unchanged.348*349* @param NaN the string representing "not a number"350*/351public void setNaN(String NaN) {352this.NaN = NaN;353}354355/**356* Gets the character used to represent minus sign. If no explicit357* negative format is specified, one is formed by prefixing358* minusSign to the positive format.359*360* @return the character representing minus sign361*/362public char getMinusSign() {363return minusSign;364}365366/**367* Sets the character used to represent minus sign. If no explicit368* negative format is specified, one is formed by prefixing369* minusSign to the positive format.370*371* @param minusSign the character representing minus sign372*/373public void setMinusSign(char minusSign) {374this.minusSign = minusSign;375}376377/**378* Returns the currency symbol for the currency of these379* DecimalFormatSymbols in their locale.380*381* @return the currency symbol382* @since 1.2383*/384public String getCurrencySymbol()385{386return currencySymbol;387}388389/**390* Sets the currency symbol for the currency of these391* DecimalFormatSymbols in their locale.392*393* @param currency the currency symbol394* @since 1.2395*/396public void setCurrencySymbol(String currency)397{398currencySymbol = currency;399}400401/**402* Returns the ISO 4217 currency code of the currency of these403* DecimalFormatSymbols.404*405* @return the currency code406* @since 1.2407*/408public String getInternationalCurrencySymbol()409{410return intlCurrencySymbol;411}412413/**414* Sets the ISO 4217 currency code of the currency of these415* DecimalFormatSymbols.416* If the currency code is valid (as defined by417* {@link java.util.Currency#getInstance(java.lang.String) Currency.getInstance}),418* this also sets the currency attribute to the corresponding Currency419* instance and the currency symbol attribute to the currency's symbol420* in the DecimalFormatSymbols' locale. If the currency code is not valid,421* then the currency attribute is set to null and the currency symbol422* attribute is not modified.423*424* @param currencyCode the currency code425* @see #setCurrency426* @see #setCurrencySymbol427* @since 1.2428*/429public void setInternationalCurrencySymbol(String currencyCode)430{431intlCurrencySymbol = currencyCode;432currency = null;433if (currencyCode != null) {434try {435currency = Currency.getInstance(currencyCode);436currencySymbol = currency.getSymbol();437} catch (IllegalArgumentException e) {438}439}440}441442/**443* Gets the currency of these DecimalFormatSymbols. May be null if the444* currency symbol attribute was previously set to a value that's not445* a valid ISO 4217 currency code.446*447* @return the currency used, or null448* @since 1.4449*/450public Currency getCurrency() {451return currency;452}453454/**455* Sets the currency of these DecimalFormatSymbols.456* This also sets the currency symbol attribute to the currency's symbol457* in the DecimalFormatSymbols' locale, and the international currency458* symbol attribute to the currency's ISO 4217 currency code.459*460* @param currency the new currency to be used461* @exception NullPointerException if <code>currency</code> is null462* @since 1.4463* @see #setCurrencySymbol464* @see #setInternationalCurrencySymbol465*/466public void setCurrency(Currency currency) {467if (currency == null) {468throw new NullPointerException();469}470this.currency = currency;471intlCurrencySymbol = currency.getCurrencyCode();472currencySymbol = currency.getSymbol(locale);473}474475476/**477* Returns the monetary decimal separator.478*479* @return the monetary decimal separator480* @since 1.2481*/482public char getMonetaryDecimalSeparator()483{484return monetarySeparator;485}486487/**488* Sets the monetary decimal separator.489*490* @param sep the monetary decimal separator491* @since 1.2492*/493public void setMonetaryDecimalSeparator(char sep)494{495monetarySeparator = sep;496}497498//------------------------------------------------------------499// BEGIN Package Private methods ... to be made public later500//------------------------------------------------------------501502/**503* Returns the character used to separate the mantissa from the exponent.504*/505char getExponentialSymbol()506{507return exponential;508}509/**510* Returns the string used to separate the mantissa from the exponent.511* Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.512*513* @return the exponent separator string514* @see #setExponentSeparator(java.lang.String)515* @since 1.6516*/517public String getExponentSeparator()518{519return exponentialSeparator;520}521522/**523* Sets the character used to separate the mantissa from the exponent.524*/525void setExponentialSymbol(char exp)526{527exponential = exp;528}529530/**531* Sets the string used to separate the mantissa from the exponent.532* Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.533*534* @param exp the exponent separator string535* @exception NullPointerException if <code>exp</code> is null536* @see #getExponentSeparator()537* @since 1.6538*/539public void setExponentSeparator(String exp)540{541if (exp == null) {542throw new NullPointerException();543}544exponentialSeparator = exp;545}546547548//------------------------------------------------------------549// END Package Private methods ... to be made public later550//------------------------------------------------------------551552/**553* Standard override.554*/555@Override556public Object clone() {557try {558return (DecimalFormatSymbols)super.clone();559// other fields are bit-copied560} catch (CloneNotSupportedException e) {561throw new InternalError(e);562}563}564565/**566* Override equals.567*/568@Override569public boolean equals(Object obj) {570if (obj == null) return false;571if (this == obj) return true;572if (getClass() != obj.getClass()) return false;573DecimalFormatSymbols other = (DecimalFormatSymbols) obj;574return (zeroDigit == other.zeroDigit &&575groupingSeparator == other.groupingSeparator &&576decimalSeparator == other.decimalSeparator &&577percent == other.percent &&578perMill == other.perMill &&579digit == other.digit &&580minusSign == other.minusSign &&581patternSeparator == other.patternSeparator &&582infinity.equals(other.infinity) &&583NaN.equals(other.NaN) &&584currencySymbol.equals(other.currencySymbol) &&585intlCurrencySymbol.equals(other.intlCurrencySymbol) &&586currency == other.currency &&587monetarySeparator == other.monetarySeparator &&588exponentialSeparator.equals(other.exponentialSeparator) &&589locale.equals(other.locale));590}591592/**593* Override hashCode.594*/595@Override596public int hashCode() {597int result = zeroDigit;598result = result * 37 + groupingSeparator;599result = result * 37 + decimalSeparator;600return result;601}602603/**604* Initializes the symbols from the FormatData resource bundle.605*/606private void initialize( Locale locale ) {607this.locale = locale;608609// get resource bundle data610LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);611// Avoid potential recursions612if (!(adapter instanceof ResourceBundleBasedAdapter)) {613adapter = LocaleProviderAdapter.getResourceBundleBased();614}615Object[] data = adapter.getLocaleResources(locale).getDecimalFormatSymbolsData();616String[] numberElements = (String[]) data[0];617618decimalSeparator = numberElements[0].charAt(0);619groupingSeparator = numberElements[1].charAt(0);620patternSeparator = numberElements[2].charAt(0);621percent = numberElements[3].charAt(0);622zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.623digit = numberElements[5].charAt(0);624minusSign = numberElements[6].charAt(0);625exponential = numberElements[7].charAt(0);626exponentialSeparator = numberElements[7]; //string representation new since 1.6627perMill = numberElements[8].charAt(0);628infinity = numberElements[9];629NaN = numberElements[10];630631// Try to obtain the currency used in the locale's country.632// Check for empty country string separately because it's a valid633// country ID for Locale (and used for the C locale), but not a valid634// ISO 3166 country code, and exceptions are expensive.635if (locale.getCountry().length() > 0) {636try {637currency = Currency.getInstance(locale);638} catch (IllegalArgumentException e) {639// use default values below for compatibility640}641}642if (currency != null) {643intlCurrencySymbol = currency.getCurrencyCode();644if (data[1] != null && data[1] == intlCurrencySymbol) {645currencySymbol = (String) data[2];646} else {647currencySymbol = currency.getSymbol(locale);648data[1] = intlCurrencySymbol;649data[2] = currencySymbol;650}651} else {652// default values653intlCurrencySymbol = "XXX";654try {655currency = Currency.getInstance(intlCurrencySymbol);656} catch (IllegalArgumentException e) {657}658currencySymbol = "\u00A4";659}660// Currently the monetary decimal separator is the same as the661// standard decimal separator for all locales that we support.662// If that changes, add a new entry to NumberElements.663monetarySeparator = decimalSeparator;664}665666/**667* Reads the default serializable fields, provides default values for objects668* in older serial versions, and initializes non-serializable fields.669* If <code>serialVersionOnStream</code>670* is less than 1, initializes <code>monetarySeparator</code> to be671* the same as <code>decimalSeparator</code> and <code>exponential</code>672* to be 'E'.673* If <code>serialVersionOnStream</code> is less than 2,674* initializes <code>locale</code>to the root locale, and initializes675* If <code>serialVersionOnStream</code> is less than 3, it initializes676* <code>exponentialSeparator</code> using <code>exponential</code>.677* Sets <code>serialVersionOnStream</code> back to the maximum allowed value so that678* default serialization will work properly if this object is streamed out again.679* Initializes the currency from the intlCurrencySymbol field.680*681* @since JDK 1.1.6682*/683private void readObject(ObjectInputStream stream)684throws IOException, ClassNotFoundException {685stream.defaultReadObject();686if (serialVersionOnStream < 1) {687// Didn't have monetarySeparator or exponential field;688// use defaults.689monetarySeparator = decimalSeparator;690exponential = 'E';691}692if (serialVersionOnStream < 2) {693// didn't have locale; use root locale694locale = Locale.ROOT;695}696if (serialVersionOnStream < 3) {697// didn't have exponentialSeparator. Create one using exponential698exponentialSeparator = Character.toString(exponential);699}700serialVersionOnStream = currentSerialVersion;701702if (intlCurrencySymbol != null) {703try {704currency = Currency.getInstance(intlCurrencySymbol);705} catch (IllegalArgumentException e) {706}707}708}709710/**711* Character used for zero.712*713* @serial714* @see #getZeroDigit715*/716private char zeroDigit;717718/**719* Character used for thousands separator.720*721* @serial722* @see #getGroupingSeparator723*/724private char groupingSeparator;725726/**727* Character used for decimal sign.728*729* @serial730* @see #getDecimalSeparator731*/732private char decimalSeparator;733734/**735* Character used for per mille sign.736*737* @serial738* @see #getPerMill739*/740private char perMill;741742/**743* Character used for percent sign.744* @serial745* @see #getPercent746*/747private char percent;748749/**750* Character used for a digit in a pattern.751*752* @serial753* @see #getDigit754*/755private char digit;756757/**758* Character used to separate positive and negative subpatterns759* in a pattern.760*761* @serial762* @see #getPatternSeparator763*/764private char patternSeparator;765766/**767* String used to represent infinity.768* @serial769* @see #getInfinity770*/771private String infinity;772773/**774* String used to represent "not a number".775* @serial776* @see #getNaN777*/778private String NaN;779780/**781* Character used to represent minus sign.782* @serial783* @see #getMinusSign784*/785private char minusSign;786787/**788* String denoting the local currency, e.g. "$".789* @serial790* @see #getCurrencySymbol791*/792private String currencySymbol;793794/**795* ISO 4217 currency code denoting the local currency, e.g. "USD".796* @serial797* @see #getInternationalCurrencySymbol798*/799private String intlCurrencySymbol;800801/**802* The decimal separator used when formatting currency values.803* @serial804* @since JDK 1.1.6805* @see #getMonetaryDecimalSeparator806*/807private char monetarySeparator; // Field new in JDK 1.1.6808809/**810* The character used to distinguish the exponent in a number formatted811* in exponential notation, e.g. 'E' for a number such as "1.23E45".812* <p>813* Note that the public API provides no way to set this field,814* even though it is supported by the implementation and the stream format.815* The intent is that this will be added to the API in the future.816*817* @serial818* @since JDK 1.1.6819*/820private char exponential; // Field new in JDK 1.1.6821822/**823* The string used to separate the mantissa from the exponent.824* Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.825* <p>826* If both <code>exponential</code> and <code>exponentialSeparator</code>827* exist, this <code>exponentialSeparator</code> has the precedence.828*829* @serial830* @since 1.6831*/832private String exponentialSeparator; // Field new in JDK 1.6833834/**835* The locale of these currency format symbols.836*837* @serial838* @since 1.4839*/840private Locale locale;841842// currency; only the ISO code is serialized.843private transient Currency currency;844845// Proclaim JDK 1.1 FCS compatibility846static final long serialVersionUID = 5772796243397350300L;847848// The internal serial version which says which version was written849// - 0 (default) for version up to JDK 1.1.5850// - 1 for version from JDK 1.1.6, which includes two new fields:851// monetarySeparator and exponential.852// - 2 for version from J2SE 1.4, which includes locale field.853// - 3 for version from J2SE 1.6, which includes exponentialSeparator field.854private static final int currentSerialVersion = 3;855856/**857* Describes the version of <code>DecimalFormatSymbols</code> present on the stream.858* Possible values are:859* <ul>860* <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6.861*862* <li><b>1</b>: Versions written by JDK 1.1.6 or later, which include863* two new fields: <code>monetarySeparator</code> and <code>exponential</code>.864* <li><b>2</b>: Versions written by J2SE 1.4 or later, which include a865* new <code>locale</code> field.866* <li><b>3</b>: Versions written by J2SE 1.6 or later, which include a867* new <code>exponentialSeparator</code> field.868* </ul>869* When streaming out a <code>DecimalFormatSymbols</code>, the most recent format870* (corresponding to the highest allowable <code>serialVersionOnStream</code>)871* is always written.872*873* @serial874* @since JDK 1.1.6875*/876private int serialVersionOnStream = currentSerialVersion;877}878879880