-Duser.language选项是VM属性

时间:2015-02-04 06:25:09

标签: java

我对传递-Duser.language选项很困惑。我们可以通过调用System.getProperty("user.language)在我们的应用程序中提取它,但是如果我们将Locale.setDefault()设置为其他语言,它是否会覆盖我们作为vm args传递的user.language。 即使我设置了System.setProperty("user.language","someotherlang"),它是否会覆盖我们传递的user.language

感谢。

1 个答案:

答案 0 :(得分:2)

首先,使用-D...传递给JVM的所有选项都称为系统属性。如您所知,您可以使用System.getProperty(...)访问它们。您甚至可以通过添加,删除和更改键值对来更改这些属性(如果没有限制性安全管理器)。

关于语言环境设置,请查看Locale实现(JDK8)的有趣部分:

public final class Locale implements Cloneable, Serializable {
    [...]
    private volatile static Locale defaultLocale = initDefault();
    [...]
    private static Locale initDefault() {
        String language, region, script, country, variant;
        language = AccessController.doPrivileged(new GetPropertyAction("user.language", "en"));
        [...] // here other properties are also retrieved
        return getInstance(language, script, country, variant, null);
    }
    [...]
}

因此,第一次访问类Locale时,它也被初始化,这也意味着静态变量defaultLocale相对于上述系统属性的初始化。

如果您以后更改其中一个系统属性(" user.language"例如),这对私有类变量defaultLocale没有任何影响。

另一方面,您可以通过调用Locale.setDefault(...)(重新)设置默认语言环境。让我们来看看它的实现:

public static synchronized void setDefault(Locale newLocale) {
    setDefault(Category.DISPLAY, newLocale);
    setDefault(Category.FORMAT, newLocale);
    defaultLocale = newLocale;
}

这会调用其他设置方法,所以让我们看一下:

public static synchronized void setDefault(Locale.Category category, Locale newLocale) {
    [...]
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) sm.checkPermission(new PropertyPermission("user.language", "write"));
    switch (category) {
    case DISPLAY: defaultDisplayLocale = newLocale; break;
    case FORMAT: defaultFormatLocale = newLocale; break;
    default: assert false: "Unknown Category";
    }
}

如您所见,私有类变量defaulLocale设置为您要设置的新区域设置,但是系统属性" user.language"没有碰到。

这意味着,关于语言环境的系统属性用于初始化,然后它们就不再有趣了。

实际上,这是配置应用程序的一些标准行为。即使我使用这种机制:读取系统属性以初始化我的组件(如果未设置系统属性,则使用某些默认值),但不再触及系统属性。