< prev index next >

src/java.base/share/classes/java/util/Locale.java

Print this page
rev 54349 : 8221701: Archive constant BaseLocales
Reviewed-by: TBD

@@ -482,105 +482,161 @@
  * @author Mark Davis
  * @since 1.1
  */
 public final class Locale implements Cloneable, Serializable {
 
-    private static final  Cache LOCALECACHE = new Cache();
-
     /** Useful constant for language.
      */
-    public static final Locale ENGLISH = createConstant("en", "");
+    public static final Locale ENGLISH;
 
     /** Useful constant for language.
      */
-    public static final Locale FRENCH = createConstant("fr", "");
+    public static final Locale FRENCH;
 
     /** Useful constant for language.
      */
-    public static final Locale GERMAN = createConstant("de", "");
+    public static final Locale GERMAN;
 
     /** Useful constant for language.
      */
-    public static final Locale ITALIAN = createConstant("it", "");
+    public static final Locale ITALIAN;
 
     /** Useful constant for language.
      */
-    public static final Locale JAPANESE = createConstant("ja", "");
+    public static final Locale JAPANESE;
 
     /** Useful constant for language.
      */
-    public static final Locale KOREAN = createConstant("ko", "");
+    public static final Locale KOREAN;
 
     /** Useful constant for language.
      */
-    public static final Locale CHINESE = createConstant("zh", "");
+    public static final Locale CHINESE;
 
     /** Useful constant for language.
      */
-    public static final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
+    public static final Locale SIMPLIFIED_CHINESE;
 
     /** Useful constant for language.
      */
-    public static final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
+    public static final Locale TRADITIONAL_CHINESE;
 
     /** Useful constant for country.
      */
-    public static final Locale FRANCE = createConstant("fr", "FR");
+    public static final Locale FRANCE;
 
     /** Useful constant for country.
      */
-    public static final Locale GERMANY = createConstant("de", "DE");
+    public static final Locale GERMANY;
 
     /** Useful constant for country.
      */
-    public static final Locale ITALY = createConstant("it", "IT");
+    public static final Locale ITALY;
 
     /** Useful constant for country.
      */
-    public static final Locale JAPAN = createConstant("ja", "JP");
+    public static final Locale JAPAN;
 
     /** Useful constant for country.
      */
-    public static final Locale KOREA = createConstant("ko", "KR");
+    public static final Locale KOREA;
 
     /** Useful constant for country.
      */
-    public static final Locale CHINA = SIMPLIFIED_CHINESE;
+    public static final Locale UK;
 
     /** Useful constant for country.
      */
-    public static final Locale PRC = SIMPLIFIED_CHINESE;
+    public static final Locale US;
 
     /** Useful constant for country.
      */
-    public static final Locale TAIWAN = TRADITIONAL_CHINESE;
+    public static final Locale CANADA;
 
     /** Useful constant for country.
      */
-    public static final Locale UK = createConstant("en", "GB");
+    public static final Locale CANADA_FRENCH;
+
+    /**
+     * Useful constant for the root locale.  The root locale is the locale whose
+     * language, country, and variant are empty ("") strings.  This is regarded
+     * as the base locale of all locales, and is used as the language/country
+     * neutral locale for the locale sensitive operations.
+     *
+     * @since 1.6
+     */
+    public static final Locale ROOT;
+
+    private static final Map<BaseLocale, Locale> CONSTANT_LOCALES = new HashMap<>();
+
+    static {
+        var baseLocales = BaseLocale.constantBaseLocales;
+        boolean fromArchive = baseLocales != null;
+        if (!fromArchive) {
+            baseLocales = new HashMap<>();
+        }
+        ENGLISH = constant("en", "", baseLocales, fromArchive);
+        FRENCH = constant("fr", "", baseLocales, fromArchive);
+        GERMAN = constant("de", "", baseLocales, fromArchive);
+        ITALIAN = constant("it", "", baseLocales, fromArchive);
+        JAPANESE = constant("ja", "", baseLocales, fromArchive);
+        KOREAN = constant("ko", "", baseLocales, fromArchive);
+        CHINESE = constant("zh", "", baseLocales, fromArchive);
+        SIMPLIFIED_CHINESE = constant("zh", "CN", baseLocales, fromArchive);
+        TRADITIONAL_CHINESE = constant("zh", "TW", baseLocales, fromArchive);
+        FRANCE = constant("fr", "FR", baseLocales, fromArchive);
+        GERMANY = constant("de", "DE", baseLocales, fromArchive);
+        ITALY = constant("it", "IT", baseLocales, fromArchive);
+        JAPAN = constant("ja", "JP", baseLocales, fromArchive);
+        KOREA = constant("ko", "KR", baseLocales, fromArchive);
+        UK = constant("en", "GB", baseLocales, fromArchive);
+        US = constant("en", "US", baseLocales, fromArchive);
+        CANADA = constant("en", "CA", baseLocales, fromArchive);
+        CANADA_FRENCH = constant("fr", "CA", baseLocales, fromArchive);
+        ROOT = constant("", "", baseLocales, fromArchive);
+        if (!fromArchive) {
+            BaseLocale.constantBaseLocales = Map.copyOf(baseLocales);
+        }
+    }
 
     /** Useful constant for country.
      */
-    public static final Locale US = createConstant("en", "US");
+    public static final Locale CHINA = SIMPLIFIED_CHINESE;
 
     /** Useful constant for country.
      */
-    public static final Locale CANADA = createConstant("en", "CA");
+    public static final Locale PRC = SIMPLIFIED_CHINESE;
 
     /** Useful constant for country.
      */
-    public static final Locale CANADA_FRENCH = createConstant("fr", "CA");
+    public static final Locale TAIWAN = TRADITIONAL_CHINESE;
 
     /**
-     * Useful constant for the root locale.  The root locale is the locale whose
-     * language, country, and variant are empty ("") strings.  This is regarded
-     * as the base locale of all locales, and is used as the language/country
-     * neutral locale for the locale sensitive operations.
-     *
-     * @since 1.6
+     * This method must be called only for creating the Locale.*
+     * constants due to making shortcuts.
      */
-    public static final Locale ROOT = createConstant("", "");
+    private static Locale constant(String lang,
+                                   String country,
+                                   Map<String, Map<String, BaseLocale>> baseLocaleMap,
+                                   boolean fromArchive) {
+        BaseLocale base;
+        if (fromArchive) {
+            var countryMap = baseLocaleMap.get(lang);
+            base = countryMap.get(country);
+        } else {
+            base = BaseLocale.createInstance(lang, country);
+            var countryMap = baseLocaleMap.get(lang);
+            if (countryMap == null) {
+                countryMap = new HashMap<>();
+                baseLocaleMap.put(lang, countryMap);
+            }
+            countryMap.put(country, base);
+        }
+        Locale locale = new Locale(base, null);
+        CONSTANT_LOCALES.put(base, locale);
+        return locale;
+    }
 
     /**
      * The key for the private use extension ('x').
      *
      * @see #getExtension(char)

@@ -707,11 +763,11 @@
      * @param variant Any arbitrary value used to indicate a variation of a <code>Locale</code>.
      * See the <code>Locale</code> class description for the details.
      * @exception NullPointerException thrown if any argument is null.
      */
     public Locale(String language, String country, String variant) {
-        if (language== null || country == null || variant == null) {
+        if (language == null || country == null || variant == null) {
             throw new NullPointerException();
         }
         baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
         localeExtensions = getCompatibilityExtensions(language, "", country, variant);
     }

@@ -765,19 +821,10 @@
     public Locale(String language) {
         this(language, "", "");
     }
 
     /**
-     * This method must be called only for creating the Locale.*
-     * constants due to making shortcuts.
-     */
-    private static Locale createConstant(String lang, String country) {
-        BaseLocale base = BaseLocale.createInstance(lang, country);
-        return getInstance(base, null);
-    }
-
-    /**
      * Returns a <code>Locale</code> constructed from the given
      * <code>language</code>, <code>country</code> and
      * <code>variant</code>. If the same <code>Locale</code> instance
      * is available in the cache, then that instance is
      * returned. Otherwise, a new <code>Locale</code> instance is

@@ -807,18 +854,25 @@
         return getInstance(baseloc, extensions);
     }
 
     static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
         if (extensions == null) {
-            return LOCALECACHE.get(baseloc);
+            Locale locale = CONSTANT_LOCALES.get(baseloc);
+            if (locale != null) {
+                return locale;
+            }
+            return Cache.LOCALECACHE.get(baseloc);
         } else {
             LocaleKey key = new LocaleKey(baseloc, extensions);
-            return LOCALECACHE.get(key);
+            return Cache.LOCALECACHE.get(key);
         }
     }
 
     private static class Cache extends LocaleObjectCache<Object, Locale> {
+
+        private static final Cache LOCALECACHE = new Cache();
+
         private Cache() {
         }
 
         @Override
         protected Locale createObject(Object key) {

@@ -975,12 +1029,15 @@
             getDefaultExtensions(props.getProperty(category.extensionsKey, ""))
                 .orElse(defaultLocale.getLocaleExtensions()));
     }
 
     private static Optional<LocaleExtensions> getDefaultExtensions(String extensionsProp) {
-        LocaleExtensions exts = null;
+        if (LocaleUtils.isEmpty(extensionsProp)) {
+            return Optional.empty();
+        }
 
+        LocaleExtensions exts = null;
         try {
             exts = new InternalLocaleBuilder()
                 .setExtensions(extensionsProp)
                 .getLocaleExtensions();
         } catch (LocaleSyntaxException e) {

@@ -2306,10 +2363,11 @@
         String language = (String)fields.get("language", "");
         String script = (String)fields.get("script", "");
         String country = (String)fields.get("country", "");
         String variant = (String)fields.get("variant", "");
         String extStr = (String)fields.get("extensions", "");
+
         baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
         if (!extStr.isEmpty()) {
             try {
                 InternalLocaleBuilder bldr = new InternalLocaleBuilder();
                 bldr.setExtensions(extStr);
< prev index next >