Properties 类是 Java 中一个非常重要且常用的类,它继承自 Hashtable,主要用于读取和写入应用程序的配置参数,这些配置参数通常以“键=值”的形式存储在 .properties 文件中。

Properties 类的核心概念
Properties 类本质上是一个键值对的集合,类似于 HashMap<String, String>,但它有几个关键特性:
- 键和值都是字符串类型:与
HashMap可以存储任意类型的键和值不同,Properties的键和值都强制要求是String类型。 - 持久化存储:
Properties类提供了非常方便的方法,可以将键值对直接写入.properties文件,也可以从.properties文件中读取。 - 线程安全(部分):虽然
Properties继承自Hashtable(线程安全),但许多常用方法(如load()和store())本身不是线程安全的,在多线程环境中使用时仍需注意同步问题。 - 处理注释和有序性:
.properties文件可以包含注释(以 或 开头),并且键值对的顺序是有意义的。Properties类在读写时会保留这些特性。
主要构造方法
Properties 类提供了几个构造方法,最常用的是无参构造方法:
// 创建一个空的 Properties 对象 Properties properties = new Properties();
还可以传入一个默认的 Properties 对象,当查找一个键时,如果当前对象中没有找到,就会在默认对象中查找。
// 创建一个带有默认值的 Properties 对象
Properties defaults = new Properties();
defaults.setProperty("default.db.url", "jdbc:default:database");
Properties properties = new Properties(defaults);
常用方法
Properties 类的方法可以分为以下几类:

1 与 Map 接口相关的方法(继承自 Hashtable)
这些方法与 HashMap 类似,但键和值都是 Object 类型(实际使用时是 String)。
| 方法 | 描述 |
|---|---|
Object setProperty(String key, String value) |
设置一个键值对(是 put() 方法的便捷版本) |
String getProperty(String key) |
根据键获取值,如果键不存在,返回 null |
String getProperty(String key, String defaultValue) |
根据键获取值,如果键不存在,返回指定的默认值 |
String remove(Object key) |
移除指定的键值对 |
Set<String> stringPropertyNames() |
返回所有键的集合(推荐使用,因为它只返回 String 类型的键) |
void clear() |
清空所有键值对 |
int size() |
返回键值对的数量 |
示例:
Properties props = new Properties();
props.setProperty("database.url", "jdbc:mysql://localhost:3306/mydb");
props.setProperty("database.user", "root");
props.setProperty("database.password", "secret");
// 获取值
String url = props.getProperty("database.url"); // "jdbc:mysql://localhost:3306/mydb"
String nonExistentKey = props.getProperty("nonexistent.key"); // null
String nonExistentKeyWithDefault = props.getProperty("nonexistent.key", "default_value"); // "default_value"
// 遍历所有键
System.out.println("--- All Properties ---");
for (String key : props.stringPropertyNames()) {
System.out.println(key + " = " + props.getProperty(key));
}
2 从输入流加载和到输出流存储
这是 Properties 类最核心的功能,用于与 .properties 文件交互。
| 方法 | 描述 |
|---|---|
void load(InputStream inStream) |
从字节输入流中加载属性列表 |
void load(Reader reader) |
从字符输入流中加载属性列表(推荐,能正确处理字符编码) |
void store(OutputStream out, String comments) |
将属性列表写入字节输出流,可以添加注释 |
void store(Writer writer, String comments) |
将属性列表写入字符输出流(推荐) |
完整示例:读写 .properties 文件
这是一个非常典型的使用场景。

1 创建配置文件 config.properties
在项目的 src 目录下创建一个名为 config.properties 的文件,内容如下:
# Database Configuration db.url=jdbc:mysql://localhost:3306/test_db db.user=admin db.password=123456 # Server Configuration server.port=8080 server.host=localhost
2 Java 代码:读取 config.properties
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesReader {
public static void main(String[] args) {
// 1. 创建 Properties 对象
Properties prop = new Properties();
// try-with-resources 语句可以自动关闭流
try (InputStream input = new FileInputStream("src/config.properties")) {
// 2. 加载 properties 文件
prop.load(input);
// 3. 读取属性值
System.out.println("Database URL: " + prop.getProperty("db.url"));
System.out.println("Database User: " + prop.getProperty("db.user"));
System.out.println("Database Password: " + prop.getProperty("db.password"));
System.out.println("Server Port: " + prop.getProperty("server.port"));
// 读取一个可能不存在的属性,并提供默认值
String cacheSize = prop.getProperty("cache.size", "1024");
System.out.println("Cache Size: " + cacheSize);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
3 Java 代码:写入 config.properties
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
public class PropertiesWriter {
public static void main(String[] args) {
// 1. 创建 Properties 对象
Properties prop = new Properties();
// 2. 设置属性
prop.setProperty("app.name", "MyCoolApp");
prop.setProperty("app.version", "1.0.0");
prop.setProperty("logging.level", "INFO");
// try-with-resources 语句
try (OutputStream output = new FileOutputStream("src/config.properties")) {
// 3. 将属性存储到文件
// 第一个参数是输出流
// 第二个参数是写入文件顶部的注释,可以为 null
prop.store(output, "Application Configuration File - Updated");
System.out.println("Properties file saved successfully!");
} catch (IOException io) {
io.printStackTrace();
}
}
}
高级用法:从类路径加载资源
在 Java 项目中,配置文件通常被打包在 JAR 或 WAR 文件中,这时,不能使用 FileInputStream,因为它只能从文件系统读取,应该使用 ClassLoader 从类路径(classpath)中加载。
假设 config.properties 在 src/main/resources 目录下,编译后它会在 classpath 的根目录。
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ClasspathPropertiesLoader {
public static void main(String[] args) {
// 使用 ClassLoader 加载资源
// 这种方式不依赖于文件系统,资源文件可以打包在 JAR 中
try (InputStream input = ClasspathPropertiesLoader.class.getClassLoader().getResourceAsStream("config.properties")) {
if (input == null) {
System.out.println("Sorry, unable to find config.properties");
return;
}
Properties prop = new Properties();
prop.load(input);
// 使用属性...
System.out.println("Loaded from classpath: " + prop.getProperty("db.url"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Properties vs. Map<String, String>
| 特性 | Properties |
Map<String, String> (如 HashMap) |
|---|---|---|
| 键/值类型 | 强制为 String |
可以是任何 Object 类型,但通常用 String |
| 持久化 | 内置支持,可直接读写 .properties 文件 |
不支持,需要手动实现序列化/反序列化 |
| 线程安全 | 继承自 Hashtable,基础操作是线程安全的,但 load/store 不是 |
HashMap 不安全;ConcurrentHashMap 或 Collections.synchronizedMap() 可用 |
| 主要用途 | 配置文件管理 | 通用内存中的键值存储 |
| 注释支持 | 支持,读写 .properties 文件时会保留注释 |
不支持 |
-
何时使用
Properties?- 当你需要读取或写入标准的
.properties配置文件时。 - 当你的配置信息需要持久化存储,并且希望格式清晰、可读性强时。
- 当配置项的键和值都是字符串时。
- 当你需要读取或写入标准的
-
何时考虑其他方案?
- 如果配置结构非常复杂(如嵌套对象、数组),可以考虑使用 JSON 或 XML 文件,并使用如 Jackson、Gson 或 JAXB 等库来解析。
- 如果只是需要在内存中临时存储一些键值对,并且不需要持久化,使用
HashMap<String, String>更简单直接。 - 如果配置项类型不限于字符串(例如需要数字、布尔值),可以考虑使用 YAML 格式(需要第三方库如 SnakeYAML)或自己编写解析逻辑。
