如何复制 java.util.Properties 对象?

我有以下字段和构造函数:

private final Properties properties;

public PropertiesExpander(Properties properties) {
    this.properties = properties;
}

最好的做法是在构造函数中复制每个可变集合。我想做一个肤浅的,独立的副本。我怎样才能做到这一点?

我的第一个想法是使用方法:putAll()

private final Properties properties = new Properties();

public PropertiesExpander(Properties properties) {
    this.properties.putAll(properties);
}

有没有更简单,更高性能或更惯用的方法可以做到这一点?也许在番石榴或Apache Commons中有一些实用工具?


答案 1

使用很棒...如果你需要留在 .它运行,开销非常小。我建议的唯一区别是出于性能原因而远离它,除非你需要它,因为它继承自Hashtable。另外,不要使用,因为它实际上不符合任何接口,只是它是一个抽象类;这将限制您的选择。请参见:“编程到接口”是什么意思?putAll()PropertiesO(number of elements)PropertiesPropertiesDictionary

从Java 2平台v1.2开始,这个类被改造以实现接口,使其成为Java Collections Framework的成员。与新的集合实现不同,它是同步的。如果不需要线程安全实现,建议使用 HashMap 代替 。如果需要线程安全的高度并发实现,则建议使用 ConcurrentHashMap 代替 Hashtable。MapHashtableHashtable

无论你做什么,不要使用 clone()它是不安全的,不高性能的。参见:Java:为什么 clone() 不能用于防御性复制?


你编辑了你的问题,询问关于番石榴和阿帕奇共享资源的问题。如果它纯粹是一个防御性副本,并且它是不可变的,我建议使用Map<String,String> map = ImmutableMap.copyOf(properties)。注意:同样,这不使用实际对象,因为除非您需要,否则不建议这样做。来自维基PropertiesHashtable

当您不希望修改集合或期望集合保持不变时,最好将其防御性地复制到不可变集合中。

重要提示:每个 Guava 不可变集合实现都拒绝空值。我们对Google的内部代码库进行了详尽的研究,该研究表明,大约5%的时间在集合中允许空元素,而其他95%的情况最好是通过在null上快速失败来满足。如果需要使用 null 值,请考虑在允许 null 的集合实现上使用 Collections.unmodifiableList 及其友元。可在此处找到更详细的建议。


答案 2

属性实现了可克隆,因此看起来您可以根据需要执行以下操作。

this.properties = (Properties) properties.clone();

将其添加到您的类中

protected Object clone() throws CloneNotSupportedException {
    return super.clone();
}

或者,如果您担心使用克隆,您的类也实现了可序列化,因此您可以执行此操作。

import org.apache.commons.lang.SerializationUtils;

this.properties = SerializationUtils.clone(properties);

物业

可克隆