我从Oracle Java教程中看到了这段代码,但对它的实际工作方式感到困惑。我正在寻找以下几个问题的答案:

1)我看不到从任何地方调用public List<Locale> getCandidateLocales(String baseName, Locale locale),那么它实际上是如何执行的?

2)作为参数传递给public List<Locale> getCandidateLocales(String baseName, Locale locale)的内容

3)public List<Locale> getCandidateLocales(String baseName, Locale locale)返回List<Locale>,返回List<Locale>的目的是什么

4)如果不满足任何public List<Locale> getCandidateLocales(String baseName, Locale locale)语句,则super.getCandidateLocales(baseName, locale);返回if,关键字super所指的是哪个类?

public class RBControl {
    public static void main(String[] args) {
    test(Locale.CHINA);
    test(new Locale("zh", "HK"));
    test(Locale.TAIWAN);
    test(Locale.CANADA);
    }

    private static void test(Locale locale) {
    ResourceBundle rb = ResourceBundle.getBundle("Internationalisation/RBControl", locale,
         new ResourceBundle.Control() {
         @Override
         public List<Locale> getCandidateLocales(String baseName, Locale locale) {
             if (baseName == null)
             throw new NullPointerException();
             if (locale.equals(new Locale("zh", "HK"))) {
             return Arrays.asList(
                 locale,
                 Locale.TAIWAN,
                 // no Locale.CHINESE here
                 Locale.ROOT);
             } else if (locale.equals(Locale.TAIWAN)) {
             return Arrays.asList(
                 locale,
                 // no Locale.CHINESE here
                 Locale.ROOT);
             }
             return super.getCandidateLocales(baseName, locale);
         }
         });
    System.out.println("locale: " + locale);
    System.out.println("\tregion: " + rb.getString("region"));
    System.out.println("\tlanguage: " + rb.getString("language"));
    }
}

最佳答案

老实说,由于您的代码风格早于Java 7(您是考古学家?),所以回答您的问题可能非常困难,但是我会尽力的。


我只能向您保证,在代码搜索有效的文件名或类名以从中加载文本资源时,实际上会调用getCandidateLocales(String, String)。例如:

// ResourceBundle.java line 1314
private static ResourceBundle getBundleImpl(String baseName, Locale locale,
                                            ClassLoader loader, Control control) {
    // (...) many lines removed
    // line 1352 - loop through files to find the best one
    ResourceBundle baseBundle = null;
    for (Locale targetLocale = locale;
         targetLocale != null;
         targetLocale = control.getFallbackLocale(baseName, targetLocale)) {
        // line 1356, there you are
        List<Locale> candidateLocales = control.getCandidateLocales(baseName, targetLocale);
        if (!isKnownControl && !checkList(candidateLocales)) {
            throw new IllegalArgumentException("Invalid Control: getCandidateLocales");
        }

        bundle = findBundle(cacheKey, candidateLocales, formats, 0, control, baseBundle);

        // lengthy comment removed for clarity
        if (isValidBundle(bundle)) {
           // checking if it is the right one, removed
        }
    }

    // logic to deal with missing file, removed
    return bundle;
}

我认为现在应该很明显,但是让我详细介绍一下。假设您以属性文件的形式发送消息:messages.properties-基本,默认语言资源,messages_fr.properties-基本法语资源,messages_fr_CA.properties-加拿大法语资源以及最后messages_de.proprties-基本德语资源。基本名称就是您可能猜到的基本文件名messages。候选语言环境是用户界面语言环境。
如果您使用的是桌面应用程序(极不可能)或移动应用程序,则只需调用Locale.getDetault(Locale.Category.DISPLAY)即可获取UI语言环境。在Java的旧版本中,它只是Locale.getDefault()。在Web应用程序中,解决方案实际上取决于技术(即Spring,JSF,Thymeleaf,Play等)和您的语言环境检测方法。无论如何,您应该首先尝试最专业的产品,而不要回退。例如,加拿大法语用户(语言标签fr-CA)应该已经看到了messages_fr_CA.properties的内容,而其他法语用户则应该看到了messages_fr.properties的内容。同样,任何其他语言环境都应遵守messages.properties的翻译。
此方法的作用是,它将为用户生成后备语言环境(即对于输入Locale.forLanguageTag("fr-CA"),它将返回输入本身,法语语言环境(“ fr”)和未定义的语言环境标记(“ und”)。一个告诉ResourceBundle使用默认文件。
如上所述,它返回后备语言环境列表。
它在父类-ResourceBundle.Control中调用该方法。您所附的代码清单中定义的匿名内部类实际上是从ResourceBundle.Control派生的。

09-26 20:44