📄 resourcebundle.java
字号:
/** * Get the appropriate ResourceBundle for the given locale. The following * strategy is used: * * <p>A sequence of candidate bundle names are generated, and tested in * this order, where the suffix 1 means the string from the specified * locale, and the suffix 2 means the string from the default locale:</p> * * <ul> * <li>baseName + "_" + language1 + "_" + country1 + "_" + variant1</li> * <li>baseName + "_" + language1 + "_" + country1</li> * <li>baseName + "_" + language1</li> * <li>baseName + "_" + language2 + "_" + country2 + "_" + variant2</li> * <li>baseName + "_" + language2 + "_" + country2</li> * <li>baseName + "_" + language2</li> * <li>baseName</li> * </ul> * * <p>In the sequence, entries with an empty string are ignored. Next, * <code>getBundle</code> tries to instantiate the resource bundle:</p> * * <ul> * <li>First, an attempt is made to load a class in the specified classloader * which is a subclass of ResourceBundle, and which has a public constructor * with no arguments, via reflection.</li> * <li>Next, a search is made for a property resource file, by replacing * '.' with '/' and appending ".properties", and using * ClassLoader.getResource(). If a file is found, then a * PropertyResourceBundle is created from the file's contents.</li> * </ul> * If no resource bundle was found, a MissingResourceException is thrown. * * <p>Next, the parent chain is implemented. The remaining candidate names * in the above sequence are tested in a similar manner, and if any results * in a resource bundle, it is assigned as the parent of the first bundle * using the <code>setParent</code> method (unless the first bundle already * has a parent).</p> * * <p>For example, suppose the following class and property files are * provided: MyResources.class, MyResources_fr_CH.properties, * MyResources_fr_CH.class, MyResources_fr.properties, * MyResources_en.properties, and MyResources_es_ES.class. The contents of * all files are valid (that is, public non-abstract subclasses of * ResourceBundle with public nullary constructors for the ".class" files, * syntactically correct ".properties" files). The default locale is * Locale("en", "UK").</p> * * <p>Calling getBundle with the shown locale argument values instantiates * resource bundles from the following sources:</p> * * <ul> * <li>Locale("fr", "CH"): result MyResources_fr_CH.class, parent * MyResources_fr.properties, parent MyResources.class</li> * <li>Locale("fr", "FR"): result MyResources_fr.properties, parent * MyResources.class</li> * <li>Locale("de", "DE"): result MyResources_en.properties, parent * MyResources.class</li> * <li>Locale("en", "US"): result MyResources_en.properties, parent * MyResources.class</li> * <li>Locale("es", "ES"): result MyResources_es_ES.class, parent * MyResources.class</li> * </ul> * * <p>The file MyResources_fr_CH.properties is never used because it is hidden * by MyResources_fr_CH.class.</p> * * @param baseName the name of the ResourceBundle * @param locale A locale * @param classLoader a ClassLoader * @return the desired resource bundle * @throws MissingResourceException if the resource bundle can't be found * @throws NullPointerException if any argument is null * @since 1.2 */ // This method is synchronized so that the cache is properly // handled. public static synchronized ResourceBundle getBundle (String baseName, Locale locale, ClassLoader classLoader) { // If the default locale changed since the last time we were called, // all cache entries are invalidated. Locale defaultLocale = Locale.getDefault(); if (defaultLocale != lastDefaultLocale) { bundleCache = new HashMap(); lastDefaultLocale = defaultLocale; } // This will throw NullPointerException if any arguments are null. lookupKey.set(baseName, locale, classLoader); Object obj = bundleCache.get(lookupKey); ResourceBundle rb = null; if (obj instanceof ResourceBundle) { return (ResourceBundle) obj; } else if (obj == nullEntry) { // Lookup has failed previously. Fall through. } else { // First, look for a bundle for the specified locale. We don't want // the base bundle this time. boolean wantBase = locale.equals(defaultLocale); ResourceBundle bundle = tryBundle(baseName, locale, classLoader, wantBase); // Try the default locale if neccessary. if (bundle == null && !locale.equals(defaultLocale)) bundle = tryBundle(baseName, defaultLocale, classLoader, true); BundleKey key = new BundleKey(baseName, locale, classLoader); if (bundle == null) { // Cache the fact that this lookup has previously failed. bundleCache.put(key, nullEntry); } else { // Cache the result and return it. bundleCache.put(key, bundle); return bundle; } } throw new MissingResourceException("Bundle " + baseName + " not found for locale " + locale + " by classloader " + classLoader, baseName, ""); } /** * Override this method to provide the resource for a keys. This gets * called by <code>getObject</code>. If you don't have a resource * for the given key, you should return null instead throwing a * MissingResourceException. You don't have to ask the parent, getObject() * already does this; nor should you throw a MissingResourceException. * * @param key the key of the resource * @return the resource for the key, or null if not in bundle * @throws NullPointerException if key is null */ protected abstract Object handleGetObject(String key); /** * This method should return all keys for which a resource exists; you * should include the enumeration of any parent's keys, after filtering out * duplicates. * * @return an enumeration of the keys */ public abstract Enumeration getKeys(); /** * Tries to load a class or a property file with the specified name. * * @param localizedName the name * @param classloader the classloader * @return the resource bundle if it was loaded, otherwise the backup */ private static ResourceBundle tryBundle(String localizedName, ClassLoader classloader) { ResourceBundle bundle = null; try { Class rbClass; if (classloader == null) rbClass = Class.forName(localizedName); else rbClass = classloader.loadClass(localizedName); // Note that we do the check up front instead of catching // ClassCastException. The reason for this is that some crazy // programs (Eclipse) have classes that do not extend // ResourceBundle but that have the same name as a property // bundle; in fact Eclipse relies on ResourceBundle not // instantiating these classes. if (ResourceBundle.class.isAssignableFrom(rbClass)) bundle = (ResourceBundle) rbClass.newInstance(); } catch (IllegalAccessException ex) {} catch (InstantiationException ex) {} catch (ClassNotFoundException ex) {} if (bundle == null) { try { InputStream is; String resourceName = localizedName.replace('.', '/') + ".properties"; if (classloader == null) is = ClassLoader.getSystemResourceAsStream(resourceName); else is = classloader.getResourceAsStream(resourceName); if (is != null) bundle = new PropertyResourceBundle(is); } catch (IOException ex) { MissingResourceException mre = new MissingResourceException ("Failed to load bundle: " + localizedName, localizedName, ""); mre.initCause(ex); throw mre; } } return bundle; } /** * Tries to load a the bundle for a given locale, also loads the backup * locales with the same language. * * @param baseName the raw bundle name, without locale qualifiers * @param locale the locale * @param classLoader the classloader * @param wantBase whether a resource bundle made only from the base name * (with no locale information attached) should be returned. * @return the resource bundle if it was loaded, otherwise the backup */ private static ResourceBundle tryBundle(String baseName, Locale locale, ClassLoader classLoader, boolean wantBase) { String language = locale.getLanguage(); String country = locale.getCountry(); String variant = locale.getVariant(); int baseLen = baseName.length(); // Build up a StringBuffer containing the complete bundle name, fully // qualified by locale. StringBuffer sb = new StringBuffer(baseLen + variant.length() + 7); sb.append(baseName); if (language.length() > 0) { sb.append('_'); sb.append(language); if (country.length() > 0) { sb.append('_'); sb.append(country); if (variant.length() > 0) { sb.append('_'); sb.append(variant); } } } // Now try to load bundles, starting with the most specialized name. // Build up the parent chain as we go. String bundleName = sb.toString(); ResourceBundle first = null; // The most specialized bundle. ResourceBundle last = null; // The least specialized bundle. while (true) { ResourceBundle foundBundle = tryBundle(bundleName, classLoader); if (foundBundle != null) { if (first == null) first = foundBundle; if (last != null) last.parent = foundBundle; foundBundle.locale = locale; last = foundBundle; } int idx = bundleName.lastIndexOf('_'); // Try the non-localized base name only if we already have a // localized child bundle, or wantBase is true. if (idx > baseLen || (idx == baseLen && (first != null || wantBase))) bundleName = bundleName.substring(0, idx); else break; } return first; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -