Java System.getProperty 和 System.getenv 区别
介绍
java.lang包在java应用中会自动导入。该包包含很多常用的类,从NullPointException到Object,Math以及String等。
java.lang.System类是一个final类,意味这我们不能创建它的实例,因此其所有方法都是static。下面我们说明两个系统方法读取系统属性和环境变量的区别,方法名称分别为getProperty and getenv。
使用System.getProperty()
java平台使用Properties 对象去提供本地系统配置信息,我们称为系统属性。系统属性包括当前用户,java运行时的版本,以及文件路径分隔符等。
下面代码中,我们使用System.getProperty(“log_dir”)
读取log_dir属性的值,也可以使用缺省值参数,确保如果属性不存在,则返回缺省值。
System.getProperty 总是返回字符串。
String log_dir = System.getProperty("log_dir","/tmp/log");
为了在运行时更新系统属性, 使用System.setProperty 方法:
System.setProperty("log_dir", "/tmp/log");
我们也可以使用属性命令行参数方式传递我们属性或配置值给应用程序:
java -jar jarName -DpropertyName=value
给app.jar应用的foo属性设置值为bar:
java -jar app -Dfoo=”bar”
使用System.getenv()
环境变量与属性类似,也是键值对形式。大多数操作系统使用环境变量,可以把配置信息传递给应用程序。
不同操作系统设置环境变量方式不同,举例,windows使用控制面板中系统程序,而Unix使用shell脚本。当创建一个进程是,缺省其继承其父进程的环境变量副本。
下面代码片段展示lambda表达式打印所有环境变量:
System.getenv().forEach((k, v) -> {
System.out.println(k + ":" + v);
});
getenv() 返回只读 Map. 尝试给 map 增加至会抛出 UnsupportedOperationException异常。获取单个变量,可以调用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();
两者差异
虽然两者本质都是map,提供字符串键和值,但有一些不同:
- 我们可以在运行时更新属性,环境变量是操作系统变量的不可变副本,不能修改。
- 属性仅在java平台中有效,而环境变量是全局的,属于操作系统级——运行在同一台机器上的所有应用都有效。
- 当打包应用是属性必须存在,但我们可以在任何时候创建环境变量。
总结
虽然在概念上是相似的,但是属性和环境变量的应用是完全不同的。选择的关键是范围问题,使用环境变量,同一个应用可以部署在多个机器上运行不同实例,可以在操作系统级别进行配置,甚至在云主机控制台中配置。无需重新编译构建应用去更新配置。
另外getProperty遵循骆驼命名约定,而getenv不是。