模块 java.base
 java.util

类 ResourceBundle.Control

java.lang.Object
java.util.ResourceBundle.Control
封闭类:
ResourceBundle

public static class ResourceBundle.Control extends Object
ResourceBundle.Control 定义了一组回调方法,在捆绑加载过程中由 ResourceBundle.getBundle 工厂方法调用。换句话说,ResourceBundle.Control 与工厂方法协作以加载资源包。回调方法的默认实现提供工厂方法执行 默认行为 所需的信息。

ResourceBundle.Control 专为部署在未命名模块中的应用程序而设计,例如支持非标准格式的资源包或以非传统约定打包本地化资源。 ResourceBundleProvider 是迁移到模块时 ResourceBundle.Control 的替代品。当调用带有 ResourceBundle.Control 参数的工厂方法时,将抛出 UnsupportedOperationException

除了回调方法之外,toBundleName toResourceName 方法的定义主要是为了方便实现回调方法。但是,可以覆盖 toBundleName 方法以在本地化资源的组织和打包方面提供不同的约定。 toResourceName 方法是 final 以避免使用错误的资源和类名分隔符。

getControl(List) getNoFallbackControl(List) 两个工厂方法提供了 ResourceBundle.Control 实例来实现默认包加载过程的常见变体。

getFormats 方法返回的格式和 getCandidateLocales 方法返回的候选locale必须在同一基础包的所有 ResourceBundle.getBundle 调用中保持一致。否则,ResourceBundle.getBundle 方法可能会返回意外的包。例如,如果 getFormats 方法在第一次调用 ResourceBundle.getBundle 时仅返回 "java.class",而在第二次调用时仅返回 "java.properties",则第二次调用将返回在第一次调用期间缓存的基于类的类。

如果 ResourceBundle.Control 实例同时被多个线程使用,则它必须是线程安全的。 ResourceBundle.getBundle 不同步调用 ResourceBundle.Control 方法。这些方法的默认实现是线程安全的。

应用程序可以指定由 getControl 工厂方法返回或从 ResourceBundle.Control 的子类创建的 ResourceBundle.Control 实例来自定义包加载过程。以下是更改默认包加载过程的示例。

示例 1

以下代码让 ResourceBundle.getBundle 仅查找基于属性的资源。

 import java.util.*;
 import static java.util.ResourceBundle.Control.*;
 ...
 ResourceBundle bundle =
  ResourceBundle.getBundle("MyResources", Locale.forLanguageTag("fr-CH"),
              ResourceBundle.Control.getControl(FORMAT_PROPERTIES));
 
给定 ResourceBundle.getBundle 描述中 例子 中的资源包,此 ResourceBundle.getBundle 调用加载 MyResources_fr_CH.properties,其父级为 MyResources_fr.properties,其父级为 MyResources.properties。 (MyResources_fr_CH.properties 未隐藏,但 MyResources_fr_CH.class 隐藏。)

示例 2

以下是使用 Properties.loadFromXML 加载基于 XML 的包的示例。

 ResourceBundle rb = ResourceBundle.getBundle("Messages",
   new ResourceBundle.Control() {
     public List<String> getFormats(String baseName) {
       if (baseName == null)
         throw new NullPointerException();
       return Arrays.asList("xml");
     }
     public ResourceBundle newBundle(String baseName,
                     Locale locale,
                     String format,
                     ClassLoader loader,
                     boolean reload)
             throws IllegalAccessException,
                 InstantiationException,
                 IOException {
       if (baseName == null || locale == null
          || format == null || loader == null)
         throw new NullPointerException();
       ResourceBundle bundle = null;
       if (format.equals("xml")) {
         String bundleName = toBundleName(baseName, locale);
         String resourceName = toResourceName(bundleName, format);
         InputStream stream = null;
         if (reload) {
           URL url = loader.getResource(resourceName);
           if (url != null) {
             URLConnection connection = url.openConnection();
             if (connection != null) {
               // Disable caches to get fresh data for
               // reloading.
               connection.setUseCaches(false);
               stream = connection.getInputStream();
             }
           }
         } else {
           stream = loader.getResourceAsStream(resourceName);
         }
         if (stream != null) {
           BufferedInputStream bis = new BufferedInputStream(stream);
           bundle = new XMLResourceBundle(bis);
           bis.close();
         }
       }
       return bundle;
     }
   });

 ...

 private static class XMLResourceBundle extends ResourceBundle {
   private Properties props;
   XMLResourceBundle(InputStream stream) throws IOException {
     props = new Properties();
     props.loadFromXML(stream);
   }
   protected Object handleGetObject(String key) {
     return props.getProperty(key);
   }
   public Enumeration<String> getKeys() {
     ...
   }
 }
 
API 注意:
ResourceBundle.Control 在命名模块中不受支持。如果在命名模块中调用带有 ResourceBundle.ControlResourceBundle.getBundle 方法,该方法将抛出 UnsupportedOperationException ResourceBundleControlProvider 的任何服务提供商在命名模块中都将被忽略。
自从:
1.6
参见:
  • 字段详细信息

    • FORMAT_DEFAULT

      public static final List <String > FORMAT_DEFAULT
      默认格式 List ,其中按顺序包含字符串 "java.class""java.properties" 。这个 List 是不可修改的。
      参见:
    • FORMAT_CLASS

      public static final List <String > FORMAT_CLASS
      仅类格式 List 包含 "java.class" 。这个 List 是不可修改的。
      参见:
    • FORMAT_PROPERTIES

      public static final List <String > FORMAT_PROPERTIES
      仅属性格式 List 包含 "java.properties" 。这个 List 是不可修改的。
      参见:
    • TTL_DONT_CACHE

      public static final long TTL_DONT_CACHE
      不缓存已加载资源包实例的生存时间常量。
      参见:
    • TTL_NO_EXPIRATION_CONTROL

      public static final long TTL_NO_EXPIRATION_CONTROL
      用于禁用缓存中已加载资源包实例的过期控制的生存时间常量。
      参见:
  • 构造方法详细信息

    • Control

      protected Control()
      唯一的构造方法。 (对于子类构造方法的调用,通常是隐式的。)
  • 方法详情

    • getControl

      public static final ResourceBundle.Control  getControl(List <String > formats)
      返回一个 ResourceBundle.Control,其中 getFormats 方法返回指定的 formatsformats 必须等于 FORMAT_PROPERTIES FORMAT_CLASS FORMAT_DEFAULT 之一。 ResourceBundle.Control 此方法返回的实例是单例且线程安全的。

      指定 FORMAT_DEFAULT 等同于实例化 ResourceBundle.Control 类,只是此方法返回一个单例。

      参数:
      formats - ResourceBundle.Control.getFormats 方法返回的格式
      返回:
      一个ResourceBundle.Control支持指定的formats
      抛出:
      NullPointerException - 如果 formatsnull
      IllegalArgumentException - 如果 formats 未知
    • getNoFallbackControl

      public static final ResourceBundle.Control  getNoFallbackControl(List <String > formats)
      返回一个 ResourceBundle.Control,其中 getFormats 方法返回指定的 formatsgetFallbackLocale 方法返回 nullformats 必须等于 FORMAT_PROPERTIES FORMAT_CLASS FORMAT_DEFAULT 之一。 ResourceBundle.Control 此方法返回的实例是单例且线程安全的。
      参数:
      formats - ResourceBundle.Control.getFormats 方法返回的格式
      返回:
      一个 ResourceBundle.Control 支持指定的 formats 没有回退 Locale 支持
      抛出:
      NullPointerException - 如果 formatsnull
      IllegalArgumentException - 如果 formats 未知
    • getFormats

      public List <String > getFormats(String  baseName)
      返回 StringList 包含用于为给定的 baseName 加载资源包的格式。 ResourceBundle.getBundle 工厂方法尝试按照列表指定的顺序加载格式的资源包。此方法返回的列表必须至少有一个 String 。基于类的资源包的预定义格式为 "java.class"基于属性 的预定义格式为 "java.properties"。以 "java." 开头的字符串保留用于将来的扩展,不得由应用程序定义的格式使用。

      不需要返回不可变(不可修改) List 。但是,返回的 List 在被 getFormats 返回后不得发生变化。

      默认实现返回 FORMAT_DEFAULT 以便 ResourceBundle.getBundle 工厂方法查找第一个基于类的资源包,然后是基于属性的资源包。

      参数:
      baseName - 资源包的基本名称,一个完全限定的类名
      返回:
      StringList 包含用于加载资源包的格式。
      抛出:
      NullPointerException - 如果 baseName 为空
      参见:
    • getCandidateLocales

      public List <Locale > getCandidateLocales(String  baseName, Locale  locale)
      返回 LocaleList 作为 baseNamelocale 的候选locale。每当工厂方法尝试为目标 Locale 查找资源包时,ResourceBundle.getBundle 工厂方法就会调用此方法。

      候选locale的顺序也对应于运行时资源查找路径(也称为母链),如果候选locale的相应资源包存在,并且它们的父级不是由加载的资源包本身定义的。如果希望将基础包作为父链的终端,列表的最后一个元素必须是根locale

      如果给定的区域设置等于 Locale.ROOT(根区域设置),则必须返回仅包含根 LocaleList。在这种情况下,ResourceBundle.getBundle 工厂方法仅加载基础包作为结果资源包。

      不需要返回不可变(不可修改) List 。但是,返回的 List 在被 getCandidateLocales 返回后不得发生变化。

      默认实现使用下面描述的规则返回包含 LocaleList。在下面的描述中, LSCV 分别代表非空语言、脚本、国家和变体。例如,[L , C ] 代表一个 Locale,它只对语言和国家有非空值。 L("xx") 的形式表示(非空)语言值是"xx"。对于所有情况,省略最终组件值为空字符串的Locales。

      1. 对于具有空脚本值的输入Locale,通过一个一个地省略最终组件来附加候选Locales,如下所示:
        • [L , C , V ]
        • [L , C ]
        • [L]
        • Locale.ROOT
      2. 对于具有非空脚本值的输入 Locale,通过省略最后一个组件来附加候选 Locale s,然后附加从 Locale 生成的候选,并恢复国家和变体:
        • [L, S, C, V]
        • [L, S, C]
        • [L , S ]
        • [L , C , V ]
        • [L , C ]
        • [L]
        • Locale.ROOT
      3. 对于具有由下划线分隔的多个子标签组成的变量值的输入 Locale,通过一个一个地省略变量子标签来生成候选 Locale s,然后在原始列表中每次出现具有完整变量值的 Locale s 之后插入它们。例如,如果变体由两个子标签 V1V2 组成:
        • [L, S, C, V1, V2]
        • [L, S, C, V1]
        • [L, S, C]
        • [L , S ]
        • [L, C, V1, V2]
        • [L, C, V1]
        • [L , C ]
        • [L]
        • Locale.ROOT
      4. 中文的特殊情况。当输入 Locale 具有语言“zh”(中文)和空脚本值时,可能会提供“Hans”(简体)或“Hant”(繁体),具体取决于国家/地区。当国家是“CN”(中国)或“SG”(新加坡)时,提供“Hans”。当国家是“HK”(中国香港特别行政区)、“MO”(中国澳门特别行政区)或“TW”(台湾)时,提供“Hant”。对于所有其他国家或国家为空时,不提供脚本。例如,对于 Locale("zh", "CN") ,候选列表将是:
        • [L(“zh”),S(“汉斯”),C(“CN”)]
        • [L(“zh”),S(“汉斯”)]
        • [L(“zh”),C(“CN”)]
        • [L(“zh”)]
        • Locale.ROOT
        对于 Locale("zh", "TW") ,候选列表将是:
        • [L(“zh”),S(“汉”),C(“台湾”)]
        • [L(“zh”),S(“汉特”)]
        • [L(“zh”),C(“TW”)]
        • [L(“zh”)]
        • Locale.ROOT
      5. 挪威语的特例。 Locale("no", "NO", "NY")Locale("nn", "NO") 都代表 Norwegian Nynorsk。当locale的语言是“nn”时,标准候选列表生成到 [L ("nn")],然后添加以下候选:
        • [L(“否”),C(“否”),V(“纽约”)]
        • [L(“否”),C(“否”)]
        • [L(“否”)]
        • Locale.ROOT
        如果locale恰好是 Locale("no", "NO", "NY") ,则首先将其转换为 Locale("nn", "NO") ,然后执行上述过程。

        此外,Java 将语言“no”视为挪威语“nb”的同义词。除了单个案例 Locale("no", "NO", "NY")(上面处理过),当输入 Locale 具有语言“no”或“nb”时,具有语言代码“no”和“nb”的候选 Locales 被交错,首先使用请求的语言,然后使用其代名词。例如,Locale("nb", "NO", "POSIX") 生成以下候选列表:

        • [L(“nb”),C(“否”),V(“POSIX”)]
        • [L(“否”),C(“否”),V(“POSIX”)]
        • [L(“NB”),C(“否”)]
        • [L(“否”),C(“否”)]
        • [L ("nb")]
        • [L(“否”)]
        • Locale.ROOT
        Locale("no", "NO", "POSIX") 将生成相同的列表,只是带有“no”的locale会出现在带有“nb”的相应locale之前。

      默认实现使用 ArrayList ,重写实现可以在将其返回给调用者之前对其进行修改。但是,getCandidateLocales 返回后,子类不得修改它。

      例如,如果给定的 baseName 是“消息”并且给定的 localeLocale("ja", "", "XX") ,那么 LocaleList

         Locale("ja", "", "XX")
         Locale("ja")
         Locale.ROOT
       
      被返回。如果找到“ja”和“”Locale的资源包,则运行时资源查找路径(父链)为:
      
         Messages_ja -> Messages
        
      参数:
      baseName - 资源包的基本名称,一个完全限定的类名
      locale - 需要资源包的locale
      返回:
      对于给定的 locale,候选 LocaleList
      抛出:
      NullPointerException - 如果 baseNamelocalenull
    • getFallbackLocale

      public Locale  getFallbackLocale(String  baseName, Locale  locale)
      返回一个 Locale 用作后备locale,以供 ResourceBundle.getBundle 工厂方法进一步搜索资源包。每次未找到 baseNamelocale 的结果资源包时,都会从工厂方法调用此方法,其中 locale 是 ResourceBundle.getBundle 的参数或此方法返回的先前后备locale。

      如果不需要进一步的回退搜索,该方法返回 null

      如果给定的 locale 不是默认实现,则默认实现返回 默认Locale。否则,返回 null

      参数:
      baseName - 资源包的基本名称,ResourceBundle.getBundle 无法为其找到任何资源包(基本包除外)的完全限定类名
      locale - ResourceBundle.getBundle 无法找到任何资源包的 Locale(基础包除外)
      返回:
      Locale 用于后备搜索,或者 null 如果不需要进一步的后备搜索。
      抛出:
      NullPointerException - 如果 baseNamelocalenull
    • newBundle

      public ResourceBundle  newBundle(String  baseName, Locale  locale, String  format, ClassLoader  loader, boolean reload) throws IllegalAccessException , InstantiationException , IOException
      为给定格式和locale的给定包名称实例化资源包,必要时使用给定的类加载器。如果没有可用于给定参数的资源包,则此方法返回 null。如果由于意外错误而无法实例化资源包,则必须通过抛出 ErrorException 而不是简单地返回 null 来报告错误。

      如果 reload 标志为 true ,则表明正在调用此方法,因为之前加载的资源包已过期。

      实现要求:
      命名模块中的资源包受 Module.getResourceAsStream 指定的封装规则的约束。当资源包对应的资源文件的包无条件打开时,指定类加载器可见的命名模块中的资源包是可访问的。

      默认实现实例化一个 ResourceBundle 如下。

      • 捆绑名称是通过调用 toBundleName(baseName, locale) 获得的。
      • 如果 format"java.class" ,则使用给定的类加载器加载包名称指定的 Class 。如果找到并可访问 Class,则实例化 ResourceBundle。如果bundle类文件的包被无条件打开,则资源bundle是可访问的;否则,将抛出 IllegalAccessException。请注意,在这个默认实现中,reload 标志在加载基于类的资源包时被忽略。
      • 如果 format"java.properties" ,则调用 toResourceName(bundlename, "properties") 以获取资源名称。如果 reloadtrue,则调用 load.getResource 以获取 URL 以创建 URLConnection 。这个URLConnection用于底层资源加载层的禁用缓存,以及得到一个InputStream。否则,将调用 loader.getResourceAsStream 以获取 InputStream 。然后,用 InputStream 构造一个 PropertyResourceBundle
      • 如果 format 既不是 "java.class" 也不是 "java.properties" ,则抛出 IllegalArgumentException
      • 如果 locale 的语言是 遗留语言代码 中的一种,无论是旧的还是新的,然后在需要时重复加载过程,并使用另一种语言的包名称。例如,“iw”代表“他”,反之亦然。
      参数:
      baseName - 资源包的基本包名,一个完全限定的类名
      locale - 应该为其实例化资源包的locale
      format - 要加载的资源包格式
      loader - 用于加载包的 ClassLoader
      reload - 指示捆绑包重新加载的标志; true 如果重新加载过期的资源包,false 否则
      返回:
      资源包实例,如果找不到则返回 null
      抛出:
      NullPointerException - 如果 bundleNamelocaleformatloadernull,或者如果 nulltoBundleName 返回
      IllegalArgumentException - 如果 format 未知,或者如果为给定参数找到的资源包含格式错误的数据。
      ClassCastException - 如果加载的类不能转换为 ResourceBundle
      IllegalAccessException - 如果类或其 nullary 构造函数不可访问。
      InstantiationException - 如果某个类的实例化由于其他原因而失败。
      ExceptionInInitializerError - 如果此方法引发的初始化失败。
      SecurityException - 如果存在安全管理器并且拒绝创建新实例。有关详细信息,请参阅 Class.newInstance()
      IOException - 如果在使用任何 I/O 操作读取资源时发生错误
      参见:
    • getTimeToLive

      public long getTimeToLive(String  baseName, Locale  locale)
      返回在此 ResourceBundle.Control 下加载的资源包的生存时间 (TTL) 值。正的生存时间值指定一个包可以保留在缓存中的毫秒数,而无需根据构建它的源数据进行验证。值 0 表示每次从缓存中检索包时都必须对其进行验证。 TTL_DONT_CACHE 指定加载的资源包不放入缓存。 TTL_NO_EXPIRATION_CONTROL 指定加载的资源包放在缓存中,没有过期控制。

      过期仅影响 ResourceBundle.getBundle 工厂方法的包加载过程。即如果工厂方法在缓存中发现资源包已经过期,工厂方法会调用needsReload 方法判断是否需要重新加载资源包。如果 needsReload 返回 true ,缓存的资源包实例将从缓存中移除。否则,该实例将保留在缓存中,并使用此方法返回的新 TTL 值进行更新。

      运行时环境的内存限制,所有缓存的资源包都可能从缓存中删除。返回一个大的正值并不意味着将加载的资源包锁定在缓存中。

      默认实现返回 TTL_NO_EXPIRATION_CONTROL

      参数:
      baseName - 指定到期值的资源包的基本名称。
      locale - 指定过期值的资源包的区域设置。
      返回:
      获取在缓存中过期的加载包的时间(0 或与缓存时间的正毫秒偏移量),TTL_NO_EXPIRATION_CONTROL 禁用过期控制,或 TTL_DONT_CACHE 禁用缓存。
      抛出:
      NullPointerException - 如果 baseNamelocalenull
    • needsReload

      public boolean needsReload(String  baseName, Locale  locale, String  format, ClassLoader  loader, ResourceBundle  bundle, long loadTime)
      根据 loadTime 给定的加载时间或其他一些标准,确定缓存中过期的 bundle 是否需要重新加载。如果需要重新加载,该方法返回truefalse否则。 loadTime 是自 Calendar纪元 以来的毫秒偏移量。

      调用 ResourceBundle.getBundle 工厂方法在用于其当前调用的 ResourceBundle.Control 实例上调用此方法,而不是在最初加载资源包的调用中使用的实例上。

      默认实现比较loadTime和资源包源数据的最后修改时间。如果确定源数据自 loadTime 以来已被修改,则返回 true。否则,返回 false。如果给定的 format 不是默认格式之一,即 "java.class""java.properties" ,则此实现假定给定的 format 与其文件后缀相同。

      参数:
      baseName - 资源包的基本包名,一个完全限定的类名
      locale - 应该为其实例化资源包的locale
      format - 要加载的资源包格式
      loader - 用于加载包的 ClassLoader
      bundle - 缓存中已过期的资源包实例
      loadTime - bundle 加载并放入缓存的时间
      返回:
      true 如果过期的包需要重新加载; false否则。
      抛出:
      NullPointerException - 如果 baseNamelocaleformatloaderbundlenull
    • toBundleName

      public String  toBundleName(String  baseName, Locale  locale)
      将给定的 baseNamelocale 转换为包名称。此方法从 newBundle needsReload 方法的默认实现中调用。

      此实现返回以下值:

         baseName + "_" + language + "_" + script + "_" + country + "_" + variant
       
      其中 languagescriptcountryvariant 分别是 locale 的语言、脚本、国家和变体值。空字符串的最终组件值与前面的“_”一起被省略。当脚本为空时,脚本值连同前面的“_”一起被省略。如果所有值都是空字符串,则返回 baseName

      例如,如果 baseName"baseName" 并且 localeLocale("ja", "", "XX"),则返回 "baseName_ja_ _XX"。如果给定的locale是 Locale("en"),则返回 "baseName_en"

      重写此方法允许应用程序在本地化资源的组织和打包中使用不同的约定。

      参数:
      baseName - 资源包的基本名称,一个完全限定的类名
      locale - 应为其加载资源包的locale
      返回:
      资源包的包名称
      抛出:
      NullPointerException - 如果 baseNamelocalenull
      参见:
    • toResourceName

      public final String  toResourceName(String  bundleName, String  suffix)
      通过将 bundleName 中出现的所有 '.' 替换为 '/' 并附加 '.' 和给定文件 suffix ,将给定的 bundleName 转换为 ClassLoader.getResource 方法所需的形式。例如,如果 bundleName"foo.bar.MyResources_ja_JP" 并且 suffix"properties",则返回 "foo/bar/MyResources_ja_JP.properties"
      参数:
      bundleName - 包名称
      suffix - 文件类型后缀
      返回:
      转换后的资源名称
      抛出:
      NullPointerException - 如果 bundleNamesuffixnull