以下分析基于JDK1.8.0_74。
1、Properties类表示一组持久属性。属性列表中的每个键及其对应值都是一个字符串。
2、可以将属性内容写出到stream中或者从stream中读取属性内容。
3、Properties类继承自Hashtable,是线程安全的类,即多个线程可以共享一个Properties对象,而不需要外部同步。
4、Hashtable的所有方法Properties对象均可以访问。
5、Properties支持文本方式和xml方式的数据存储。
(1)在文本方式中,格式为key:value,其中分隔符可以是:冒号(:)、等号(=)、空格。其中空格可以作为key的结束,同时获取的值回将分割符号两端的空格去掉。
(2)XML属性文档具有以下DOCTYPE声明:
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
注意,导出或导入属性时不访问系统URI (http://java.sun.com/dtd/properties.dtd);它只是作为一个字符串来唯一标识DTD
XML例如:
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<properties>
<comment>comments</comment>
<entry key="key1">value1</entry>
<entry key="key2">value2</entry>
<entry key="key3">value3</entry>
</properties>
6、Properties只支持1对1模式的属性设置,而且不支持多层多级属性设置。
1**、继承Hashtable<Object,Object>**
Hashtable可以理解为线程安全的HashMap,它们都实现了Map接口,内部实现几乎一样。
Hashtable与HashMap的不同点有以下几个:
(1)Hashtable是线程安全的,方法都使用了synchronized修饰。
但这里值得一提的是,平时在使用线程安全的Map时,并不推荐使用Hashtable,因为其方法使用的同步锁(对象锁,对当前实例加锁),并发执行效率较低;在Java5以后,提供了ConcurrentHashMap,可替代Hashtable的功能,或使用Collections.synchronizedMap((Map<K,V> m)方法获得线程安全的SynchronizedMap类。(ConcurrentHashMap使用的是锁分段技术,可有效提高并发访问效率,具体请自行百度;推荐使用该类达到线程安全的目的)
(2)HashMap使用的迭代器(Iterator)是fail-fast迭代器,Hashtable的迭代器(Enumerator)不是fail-fast的。
(注:fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。)
(3)HashMap可以使用null键和值,而Hashtable的键和值都不能为null。
以put(K key, V value)方法为例:
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode();
……
return null;
}
该方法判断value为null时会抛出NullPointerException,而执行后面的语句key.hashCode()时,如果key为null也会抛出NullPointerException。
2**、不建议的继承方法**
JDK1.8帮助文档中提到:
因为属性继承自Hashtable,所以put和putAll方法可以应用于Properties对象。强烈反对使用它们,因为它们允许调用者插入键或值不是字符串的条目。应该使用setProperty方法。如果在包含非字符串键或值的“受损”Properties对象上调用store或save方法,则调用将失败。类似地,如果对包含非字符串键的“受影响的”Properties对象调用propertyNames或list方法,则调用将失败。
二、重要属性
protected Properties defaults;
除了继承于Hashtable的属性,Properties仅有这一个属性。其作用在JDK1.8帮助文档中解释为:
“属性列表可以包含另一个属性列表作为其“默认值”;如果在原始属性列表中没有找到属性键,则搜索第二个属性列表。”
1、默认值的初始化:通过带参数的构造方法对其进行赋值。
2、默认值的使用:
主要使用在方法getProperty(String key),通过key获取value。即 “当原始属性列表中没有找到属性键时,搜索此默认属性列表”。
public String getProperty(String key) {
Object oval = super.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
1、无参构造方法
public Properties() {
this(null);
}
2、设置默认Properties值的构造方法
public Properties(Properties defaults) {
this.defaults = defaults;
}
1**、getProperty(String key)**
通过键获取值,如果列表中无值,再从默认Properties属性中获取值。
public String getProperty(String key) {
Object oval = super.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
2**、getProperty(String key, String defaultValue)**
通过键获取值,如果无值返回入参的值。
public String getProperty(String key, String defaultValue) {
String val = getProperty(key);
return (val == null) ? defaultValue : val;
}
3**、load(InputStream inStream)**
从字节流中加载key/value键值对,要求所有的key/value键值对是按行存储,同时是ISO-8859-1编码。
public synchronized void load(InputStream inStream) throws IOException {
load0(new LineReader(inStream));
}
private void load0 (LineReader lr) throws IOException {
……
String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);
}
4**、load(Reader reader)**
从字符流中加载key/value键值对,要求所有的键值对都是按照行来存储的。
public synchronized void load(Reader reader) throws IOException {
load0(new LineReader(reader));
}
load0方法同上。
5**、loadFromXML(InputStream in)**
从xml文件中加载property,Java7底层使用XMLUtils.load(Properties,InputStream)方法来加载;Java8对这个方法做了修改,以下源码为Java8;XML默认情况下使用UTF-8字符编码。
public synchronized void loadFromXML(InputStream in)
throws IOException, InvalidPropertiesFormatException{
XmlSupport.load(this, Objects.requireNonNull(in));
in.close();
}
private static final XmlPropertiesProvider PROVIDER = loadProvider();
static void load(Properties props, InputStream in)
throws IOException, InvalidPropertiesFormatException{
PROVIDER.load(props, in);
}
loadProvider()方法返回的是抽象类XmlPropertiesProvider的一个实现类BasicXmlPropertiesProvider,底层通过其ParserSAX来实现XML数据加载。
6**、store(Writer writer, String comments)**
将所有的property(保存defaults的)都写出到字符流中,如果给定comments的话,则可在输入设置上添加注释。
public void store(Writer writer, String comments)
throws IOException{
store0((writer instanceof BufferedWriter)?(BufferedWriter)writer
: new BufferedWriter(writer),
comments,
false);
}
7**、store(OutputStream out, String comments)**
将所有的property(保存defaults的)都写出到字节流中,默认ISO-8859-1编码,如果给定comments的话,则可在输入设置上添加注释。
public void store(OutputStream out, String comments)
throws IOException{
store0(new BufferedWriter(new OutputStreamWriter(out, "8859_1")),
comments,
true);
}
8**、storeToXML(OutputStream os, String comment, String encoding)**
数据写入到xml文件中。
public void storeToXML(OutputStream os, String comment, String encoding)
throws IOException{
XmlSupport.save(this, Objects.requireNonNull(os), comment,
Objects.requireNonNull(encoding));
}
public void storeToXML(OutputStream os, String comment)
throws IOException{
storeToXML(os, comment, "UTF-8");
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/u010188178/article/details/88826589
内容来源于网络,如有侵权,请联系作者删除!