最近在看 java 集合源码的时候,发现原来我们经常使用的 Properties 类既然继承自 Hashtable!又涨见识了!
01、摘要
在集合系列的第一章,咱们了解到,Map 的实现类有 HashMap、LinkedHashMap、TreeMap、IdentityHashMap、WeakHashMap、Hashtable、Properties 等等。
在上一章节中,咱们介绍到 Hashtable 的数据结构和算法实现,在 Java 中其实还有一个非常重要的类** Properties,它继承自 Hashtable,主要用于读取配置文件。**
本文通过看 JDK 和一些网友的博客总结,主要从 Properties 的用法实例来做介绍,如果有理解不当之处,欢迎指正。
02、简介
Properties 类是 java 工具包中非常重要的一个类,比如在实际开发中,有些变量,我们可以直接硬写入到自定义的 java 枚举类中。
但是有些变量,在测试环境、预生产环境、生产环境,变量所需要取的值都不一样,这个时候,我们可以通过使用 properties 文件来加载程序需要的配置信息,以达到一行代码,多处环境都可以运行的效果!
最常见的比如 JDBC 数据源配置文件,properties
文件以.properties
作为后缀,文件内容以键=值
格式书写,左边是变量名称,右边是变量值,用#
做注释,比如新建一个jdbc.properties
文件,内容如下:
Properties 类是 properties 文件和程序的中间桥梁,不论是从 properties 文件读取信息,还是写入信息到 properties 文件,都要经由 Properties 类。
好了,唠叨了这么多,咱们回到本文要介绍的主角 Properties!
从集合 Map 架构图可以看出,Properties 继承自 Hashtable,表示一个持久的 map 集合,属性列表以 key-value 的形式存在,Properties 类定义如下:
1 |
|
Properties 除了继承 Hashtable 中所定义的方法,Properties 也定义了以下几个常用方法,如图所示:
2.1、常用方法介绍
2.1.1、set 方法(添加修改元素)
set 方法是将指定的 key, value 对添加到 map 里,在添加元素的时候,调用了 Hashtable 的 put 方法,与 Hashtable 不同的是, key 和 value 都是字符串。
打开 Properties 的 setProperty 方法,源码如下:
1 |
|
方法测试如下:
1 |
|
输出结果:
1 |
|
2.1.2、get 方法(搜索指定元素)
get 方法根据指定的 key 值返回对应的 value,第一步是从调用 Hashtable
的 get 方法,如果有返回值,直接返回;如果没有返回值,但是初始化时传入了defaults
变量,从 defaults
变量中,也就是 Properties
中,去搜索是否有对于的变量,如果有就返回元素值。
打开 Properties 的 getProperty 方法,源码如下:
1 |
|
查看 defaults 这个变量,源码如下:
1 |
|
这个变量在什么时候赋值呢,打开源码如下:
1 |
|
可以发现,在 Properties 构造方法初始化阶段,如果你给了一个自定义的 defaults ,当调用 Hashtable
的 get 方法没有搜索到元素值的时候,并且 defaults 也不等于空,那么就会进一步在 defaults 里面进行搜索元素值。
方法测试如下:
1 |
|
输出结果:
1 |
|
2.1.3、load方法(加载配置文件)
load 方法,表示将 properties 文件以输入流的形式加载文件,并且提取里面的键、值对,将键值对元素添加到 map 中去。
打开 Properties 的 load 方法,源码如下:
1 |
|
load0 方法,源码如下:
1 |
|
好了,我们来在src/recources
目录下,新建一个custom.properties
配置文件,内容如下:
1 |
|
方法测试如下:
1 |
|
输出结果:
1 |
|
2.1.4、propertyNames方法(读取全部信息)
propertyNames 方法,表示读取 Properties 的全部信息,本质是创建一个新的 Hashtable 对象,然后将原 Hashtable 中的数据复制到新的 Hashtable 中,并将 map 中的 key 全部返回。
打开 Properties 的 propertyNames 方法,源码如下:
1 |
|
enumerate 方法,源码如下:
1 |
|
方法测试如下:
1 |
|
输出内容如下:
1 |
|
2.1.5、总结
Properties 继承自 Hashtable,大部分方法都复用于 Hashtable,比如,get、put、remove、clear 方法,与 Hashtable 不同的是, Properties中的 key 和 value 都是字符串,如果需要获取 properties 中全部内容,可以先通过迭代器或者 propertyNames 方法获取 map 中所有的 key 元素,然后遍历获取 key 和 value。
需要注意的是,Properties 中的 setProperty 、load 方法,都加了synchronized
同步锁,用来控制线程同步。
03、properties 文件的加载方式
在实际开发中,经常会遇到读取配置文件路径找不到,或者读取文件内容乱码的问题,下面简单介绍一下,properties 文件的几种常用的加载方式。
properties 加载文件的方式,大致可以分两类,第一类是使用 java.util.Properties
的 load 方法来加载文件流;第二类是使用 java.util.ResourceBundle
类来获取文件内容。
在src/recources
目录下,新建一个custom.properties
配置文件,文件编码格式为UTF-8
,内容还是以刚刚那个测试为例,各个加载方式如下!
3.1、通过文件路径来加载文件
这类方法加载文件,主要是调用 Properties 的 load 方法,获取文件路径,读取文件以流的形式加载文件。
方法如下:
1 |
|
输出结果:
1 |
|
3.2、通过当前类加载器的getResourceAsStream方法获取
这类方法加载文件,也是调用 Properties 的 load 方法,不同的是,通过类加载器来获取文件路径,如果当前文件是在src/resources
目录下,那么直接传入文件名就可以了。
方法如下:
1 |
|
输出结果:
1 |
|
3.3、使用ClassLoader类的getSystemResourceAsStream方法获取
和上面类似,也是通过类加载器来获取文件流,方法如下:
1 |
|
输出结果:
1 |
|
3.4、使用 ResourceBundle 类加载文件
ResourceBundle 类加载文件,与 Properties 有所不同,ResourceBundle 获取 properties 文件不需要加.properties
后缀名,只需要文件名即可。
ResourceBundle 是按照iso8859编码格式来读取原属性文件,如果是读取中文内容,需要进行转码处理。
方法如下:
1 |
|
输出结果:
1 |
|
04、总结
从源码上可以看出,Properties 继承自 Hashtable,大部分方法都复用于 Hashtable,与 Hashtable 不同的是, Properties 中的 key 和 value 都是字符串。
实际开发中,Properties 主要用于读取配置文件,尤其是在不同的环境下,变量值需要不一样的情况,可以通过读取配置文件来避免将变量值写死在 java 的枚举类中,以达到一行代码,多处运行的目的!
在读取 Properties 配置文件的时候,容易因文件路径找不到报错,可以参考 properties 文件加载的几种方式,如果网友还有新的加载方法,欢迎给我们留言!
05、参考
1、JDK1.7&JDK1.8 源码