java.lang包在Java应用程序中自动导入。这个包包含许多常用的类,从NullPointerException
到Object
、Math
和String
。
这个java.lang.System
系统类是最后一个类,这意味着我们不能将其子类化,因此所有方法都是静态的。
我们将研究两种读取系统属性和环境变量的系统方法之间的差异。
这些方法是getProperty
和getenv
。
使用System.getProperty()
Java平台使用Properties
对象来提供关于本地系统和配置的信息,我们称之为系统属性。
系统属性包括诸如当前用户、Java运行时的当前版本和文件路径名分隔符等信息。
在下面的代码中,我们使用System.getProperty(“log_dir”)
读取属性log_dir
的值。我们还使用默认值参数,因此如果属性不存在,getProperty
将返回/tmp/log:
String log_dir = System.getProperty("log_dir","/tmp/log");
要在运行时更新系统属性,请使用System.setProperty
属性方法:
System.setProperty("log_dir", "/tmp/log");
我们可以使用propertyName
命令行参数将自己的属性或配置值传递给应用程序,格式如下:
java -jar jarName -DpropertyName=value
将foo
的属性设置为bar.jar的值:
java -jar app -Dfoo="bar"
System.getProperty
将始终返回字符串。
使用System.getenv()
环境变量是与属性类似的键/值对。许多操作系统使用环境变量来允许将配置信息传递到应用程序中。
设置环境变量的方法因操作系统而异。例如,在Windows中,我们使用控制面板中的系统实用程序应用程序,而在Unix中,我们使用shell脚本。
创建进程时,默认情况下,它继承其父进程的克隆环境。
下面的代码片段显示如何使用lambda
表达式打印所有环境变量。
System.getenv().forEach((k, v) -> {
System.out.println(k + ":" + v);
});
getenv()
返回一个只读映射。尝试向映射添加值会引发不支持的操作异常。
要获取单个变量,请使用变量名调用getenv
:
String log_dir = System.getenv("log_dir");
另一方面,我们可以从应用程序中创建另一个进程,并向其环境中添加新的变量。
为了在Java中创建一个新的进程,我们使用ProcessBuilder
类,它有一个名为environment
的方法。这个方法返回一个Map,但这次Map不是只读的,这意味着我们可以向它添加元素
ProcessBuilder pb = new ProcessBuilder(args);
Map<String, String> env = pb.environment();
env.put("log_dir", "/tmp/log");
Process process = pb.start();
区别
尽管这两种映射本质上都是为字符串键提供字符串值的映射,但让我们看一下几个区别:
1. 当环境变量是操作系统变量的不可变副本时,我们可以在运行时更新属性。
2. 属性只包含在Java平台中,而环境变量在操作系统级别是全局的—可用于在同一台机器上运行的所有应用程序。
3. 打包应用程序时属性必须存在,但我们几乎可以在任何时候在操作系统上创建环境变量。
结论
虽然概念上相似,但属性和环境变量的应用却截然不同。
两种选择之间的选择往往是一个范围问题。通过使用环境变量,可以将同一个应用程序部署到多台计算机以运行不同的实例,并且可以在操作系统级别甚至在AWS或Azure控制台中进行配置。正在删除需要重建应用程序以更新配置的文件。
始终记住getProperty
遵循camel-case约定,而getenv
不遵循。