Java属性
Java属性类" java.util.Properties"类似于Java字符串键和值对的Java映射。 Java"属性"类可以将键,值对写入磁盘上的属性文件,然后再次读回属性。这是用于存储Java应用程序的简单配置属性的常用机制。
创建一个属性实例
要使用Java"属性"类,我们必须首先创建一个"属性"实例。我们可以通过其构造函数和Javanew
指令来实现。这是创建JavaProperties
实例的示例:
Properties properties = new Properties();
设置属性
要在Java"属性"实例中设置属性,请使用" setProperty()"方法。这是在JavaProperties
对象中设置属性(键值对)的示例:
properties.setProperty("email", "[email protected]");
本示例使用键" email"将属性设置为值" [email protected]"。
获取属性
要从Java属性对象获取属性,可以使用getProperty()方法,并将属性的键作为参数传递。这是一个从JavaProperties
实例获取属性的示例:
String email = properties.getProperty("email");
删除属性
我们可以使用Java属性实例的remove()方法从其属性中删除属性,并将要删除的属性的键作为参数传递给remove()方法。这是一个从JavaProperties
实例中删除属性的示例:
properties.remove("email");
迭代属性
我们可以通过获取Java Properties实例的密钥集并对该密钥集进行迭代,来迭代Java Properties实例的密钥。这是获得JavaProperties
的键集以迭代其所有键的示例:
Properties properties = new Properties(); properties.setProperty("key1", "value1"); properties.setProperty("key2", "value2"); properties.setProperty("key3", "value3"); Iterator keyIterator = properties.keySet().iterator(); while(keyIterator.hasNext()){ String key = (String) keyIterator.next(); String value = properties.getProperty(key); System.out.println(key + " = " + value ); }
本示例将打印出以下行:
key1 = value1 key2 = value2 key3 = value3
将属性存储到文件
我们可以将属性键,值对存储到属性文件中,以后可以再次读取。我们可以通过"属性"对象的" store()"方法存储其内容。这是将JavaProperties
的内容存储到属性文件中的示例:
Properties properties = new Properties(); properties.setProperty("property1", "value1"); properties.setProperty("property2", "value2"); properties.setProperty("property3", "value3"); try(FileWriter output = new FileWriter("data/props.properties")){ properties.store(output, "These are properties"); } catch (IOException e) { e.printStackTrace(); }
属性文件编码
默认情况下,Java"属性"文件的编码为" ISO-8859-1(Latin-1)"。但是,如今,使用UTF-8作为编码更为普遍。我们可以指定文件编码,以用作存储文件时使用的Java FileWriter的第二个参数。这是将JavaProperties
文件编码(字符集)设置为UTF-8的示例:
try(FileWriter output = new FileWriter("data/props.properties", Charset.forName("UTF-8"))){ properties.store(output, "These are properties"); } catch (IOException e) { e.printStackTrace(); }
属性文件格式
JavaProperties
属性文件由在每一行上具有一对" key = value"对的行组成。这是一个Java属性属性文件的示例:
#These are properties #Thu May 04 21:29:20 CEST 2019 property2=value2 property1=value1 property3=value3
以#开头的行是注释。注意,属性文件的第一行实际上是注释,该注释作为第二个参数传递到上一节有关将属性存储到属性文件的代码示例中的store()方法调用中。
"键=值"格式之后的行包含属性键,值对。
从文件加载属性
我们还可以通过属性文件中的load()方法将存储在属性文件中的属性重新加载到Java属性对象中。这是将属性文件加载到JavaProperties
对象中的示例:
Properties properties = new Properties(); try(FileReader fileReader = new FileReader("data/props.properties")){ properties.load(fileReader); } catch (IOException e) { e.printStackTrace(); }
加载属性文件时的文件编码
默认情况下," load()"方法将假定使用" ISO-8859-1(Latin-1)"对加载的文件进行编码。如果属性文件使用其他编码,例如" UTF-8",则必须将编码指定为Java FileReader的第二个参数,该参数用于加载属性文件。这是加载Java属性文件时将文件编码设置为UTF-8的示例:
try(FileReader fileReader = new FileReader("data/props.properties", Charset.forName("UTF-8"))){ properties.load(fileReader); } catch (IOException e) { e.printStackTrace(); }
将属性存储到XML文件
Java"属性"类还可以通过其" storeToXML()"将存储其中的键值对写入XML文件。这是将JavaProperties
存储到XML文件的示例:
Properties properties = new Properties(); properties.setProperty("property1", "value1"); properties.setProperty("property2", "value2"); properties.setProperty("property3", "value3"); try(FileOutputStream output = new FileOutputStream("data/props.xml")){ properties.storeToXML(output, "These are properties"); } catch (IOException e) { e.printStackTrace(); }
属性XML文件编码
默认情况下,Java"属性" XML属性文件的编码为UTF-8. 注意,这是非XML属性文件的默认默认设置。如果我们需要对XML文件使用其他编码,则可以这样做。我们可以指定文件编码,以用作storeToXML方法的第三个参数。这是一个使用ISO-8859-1编码将Java属性存储为XML的示例:
try(FileOutputStream output = new FileOutputStream("data/props.xml")){ properties.storeToXML(output, "These are properties", Charset.forName("ISO-8859-1")); } catch (IOException e) { e.printStackTrace(); }
XML属性文件格式
上一节中的示例中存储到XML文件的JavaProperties
对象如下所示:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>These are properties</comment> <entry key="property2">value2</entry> <entry key="property1">value1</entry> <entry key="property3">value3</entry> </properties>
请注意,传递给storeToXML()方法的注释是如何包含在comment
XML元素中,而不是包含在XML注释(<!-->
)中的。
从XML文件加载属性
我们可以通过XML属性文件的loadFromXML()方法将其属性加载到Java属性对象中。这是将属性从XML属性文件加载到JavaProperties
对象中的示例:
Properties properties = new Properties(); try(FileInputStream fileInputStream = new FileInputStream("data/props.xml")){ properties.loadFromXML(fileInputStream); } catch(IOException e){ e.printStackTrace(); }
加载XML属性文件时的文件编码
默认情况下," loadFromXML()"方法将假定XML文件使用" UTF-8"编码存储。请注意,这与非XML属性文件的默认设置相反。如果XML文件使用其他编码,例如ISO-8859-1(Latin-1),则XML文件必须其中指定编码。这是通过将以下行作为XML属性文件的第一行来完成的:
<?xml version="1.0" encoding="ISO-8859-1"?>
从类路径加载属性
可以从类路径上可用的文件将属性加载到Java"属性"中。因此,该文件可以与加载属性的应用程序位于同一JAR文件中,或者在执行Java应用程序时位于Java类路径上可用的另一个JAR文件或者目录中。
要从类路径上可用的文件加载属性,我们需要首先获取一个" Class"实例。在下面的示例中,我从包含我的应用程序的main()方法的类中获取它:
Class aClass = PropertiesExample.class;
一旦有了Class实例,就可以调用其getResourceAsStream()方法,该方法返回引用该文件的Java InputStream。这是从类路径获取对文件的引用的示例:
InputStream inputStream = aClass.getResourceAsStream("/myProperties.properties");
该文件必须位于类路径的根目录中。如果将其放在子目录中,则传递给getResourceAsStream()
的路径应反映出这一点。例如。 / subdir / myProperties.properties
。
使用InputStream,我们可以使用本Java属性教程前面介绍的load()或者loadFromXML()方法将文件加载到Java Properties实例中。使用哪种方法取决于属性文件使用的格式。这是一个通过load()
加载属性的例子:
Class aClass = PropertiesExample.class; InputStream inputStream = aClass.getResourceAsStream("/myProperties.properties"); Properties fromClasspath = new Properties(); try { fromClasspath.load(inputStream); } catch (IOException e) { e.printStackTrace(); }
ResourceBundle属性
Java包含一种特殊类型的属性,称为ResourceBundle。 " ResourceBundle"是一束文件,这些文件一起构成了一个文件包。通常,每个文件将包含一组专门针对特定语言的属性。因此,每个文件通常将包含相同的属性键集,但是具有特定于该文件所针对的语言的值。 ResourceBundle属性文件通常是从类路径加载的。
ResourceBundle是国际化应用程序的常用方法。我在Java国际化教程中介绍了Java应用程序的国际化。在Java ResourceBundle教程中,ResourceBundle
类是该教程的一部分。
默认属性
Java"属性"类可以为未在"属性"实例中注册任何键的属性提供默认属性值。有两种使用默认属性值的方法。这些是:
- 为getProperty()方法提供默认值。
- 创建新的"属性"实例时,提供一个包含默认值的"属性"实例。
以下各节将显示这两种为属性提供默认值的方式的示例。
使用getProperty()的默认值
" getProperty()"方法具有一个版本,该版本采用一个额外的参数,如果" Properties"实例不包含给定键的值,则返回默认值。以下是使用默认值调用getProperty()
的示例:
Properties properties = new Properties(); String preferredLanguage = properties.getProperty("preferredLanguage", "Danish");
如果Properties
实例不包含键preferredLanguage
的属性,那么将返回值" Danish"而不是返回null
,如果没有将默认值传递给getProperty(),该值将返回。
具有默认属性实例的默认值
可以使用另一个包含默认值的Java实例实例化Java实例类,该实例包含默认值,以供新创建的"实例"实例不包含所请求的属性键的值时使用。这是使用另一个提供默认值的"属性"实例实例化"属性"实例的示例:
Properties defaultProperties = new Properties(); defaultProperties.setProperty("preferredLanguage", "Danish"); Properties newProperties = new Properties(defaultProperties); String language = newProperties.getProperty("preferredLanguage"); System.out.println("Preferred language: " + language);
由于我们没有在newProperties
实例中为键preferredLanguage
设置任何属性值,因此newProperties
实例将在defaultProperties
中寻找一个值。
系统属性
Java中的系统属性是一个特殊的"属性"实例,其中包含系统特定的属性。这些系统属性是Java VM等的设置。我们可以通过System.getProperties()方法访问Java系统属性。这是获取Java系统属性的示例:
Properties systemProperties = System.getProperties();
现在,我们可以通过此"属性"实例获取并设置系统特定的属性。
System类还具有getProperty()和setProperty()方法,它们是SystemProperties实例的PropertiesProperty()和setProperty()方法的快捷方式。这是调用System.getProperty()
和System.setProperty()
的示例:
System.setProperty("key1", "value1"); String value1 = System.getProperty("key1"); //The above is equal to: Properties systemProperties = System.getProperties(); systemProperties.setProperty("key1", "value1"); String value1 = systemProperties.getProperty("key1");
通过命令行设置Java系统属性
在启动Java应用程序时,可以通过命令行上的Java命令来设置Java系统属性键和值。我们可以通过-D
参数来实现。这是通过命令行设置Java系统属性的示例:
java -Dkey1=value -cp . com.Hyman.MyApp
该命令告诉Java使用当前目录作为类路径来执行类" com.Hyman.MyApp",并将名为" key1"的"系统"属性设置为值" value1"。
在命令行上设置的系统属性也可以在运行时通过"系统属性"使用。我们可以在应用程序内部访问上述key1
属性,如下所示:
String key1Property = System.getProperty("key1");
属性是哈希表的子类-错误!
JavaProperties
类是JavaHashtable
类的子类,正如我将向我们展示的,这实际上是一个设计错误!这是一个很好的例子,说明有关何时使用继承与组合的经典OOP规则"失败了"。让我们看看如何。
作为Hashtable的子类,我们实际上可以使用Hashtable类的get()和put()方法,它们允许使用非字符串键和值。这违背了" Properties"类的目的,即充当字符串,字符串映射。这是在"属性"上使用" put()"的示例:
Properties asProperties = new Properties(); asProperties.put(123, 456); asProperties.put("abc", 999);
注意如何用非字符串值调用put()
。
为了清楚起见:请勿使用Properties类的put()和get()方法!使用这些方法可能会导致不可预测的结果。看这个例子:
Properties asProperties = new Properties(); asProperties.put("abc", 999); String abc = asProperties.getProperty("abc"); System.out.println(abc);
getProperty(" abc")
调用实际上将返回null
!
相反,如果传递给put()
的值是两个字符串,则它将按预期工作。看这个例子:
Properties asProperties = new Properties(); asProperties.put("abc", "999"); String abc = asProperties.getProperty("abc"); System.out.println(abc);
注意传递给put()
的第二个值现在也是一个字符串。现在,getProperty(" abc")
调用实际上返回字符串999
。
即使我们可以使get()和put()正常工作,我还是建议我们不要使用这些方法。坚持使用setProperty()和getProperty()方法。
如前所述,这是"是/有一个"出问题的一个示例。 Java的"属性"实例显然是"哈希表"实例,但不应共享"哈希表"接口。因此,该规则的"是"部分应解释为"应作为a使用"。使用该表达方式,不会将"属性"作为"哈希表"的子类,因为"属性"不应用作"哈希表"。
相反," Properties"类应该刚刚有一个内部" Hashtable",以保留属性键,值对。