我对传递-Duser.language
选项很困惑。我们可以通过调用System.getProperty("user.language)
在我们的应用程序中提取它,但是如果我们将Locale.setDefault()
设置为其他语言,它是否会覆盖我们作为vm args传递的user.language。
即使我设置了System.setProperty("user.language","someotherlang")
,它是否会覆盖我们传递的user.language
。
感谢。
答案 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"没有碰到。
这意味着,关于语言环境的系统属性用于初始化,然后它们就不再有趣了。
实际上,这是配置应用程序的一些标准行为。即使我使用这种机制:读取系统属性以初始化我的组件(如果未设置系统属性,则使用某些默认值),但不再触及系统属性。