【问题标题】:How to merge two java.util.Properties objects?如何合并两个 java.util.Properties 对象?
【发布时间】:2011-01-01 13:37:36
【问题描述】:

我试图在我的类中有一个默认的 java.util.Properties 对象,它接受它的默认属性,并让开发人员通过指定另一个 java.util.Properties 对象来覆盖其中的一些,但我找不到一个好的这样做的方法。

预期用途如下:

Properties defaultProperties = new Properties();
defaultProperties.put("key1", "value1");
defaultProperties.put("key2", "value2");

Properties otherProperties = new Properties();
otherProperties.put("key2", "value3");

Properties finalProperties = new Properties(defaultProperties);

//
// I'd expect to have something like:
// 
// finalProperties.merge(otherProperties);
//

【问题讨论】:

  • 有人回答但删除了答案,指出正确的方法是使用putAll()方法,这是正确的答案并达到了我想要的。我没有注意到java.util.Properties 扩展了java.util.Hashtable
  • 为什么你认为我的回答不正确?
  • 技术上没有错,但我想要的是合并两个java.util.Properties文件而不迭代其内容,这正是putAll()方法所做的。

标签: java properties


【解决方案1】:

java.util.Properties 实现了java.util.Map 接口,因此您可以将其视为这样,并使用putAll 之类的方法添加另一个Map 的内容。

但是,如果您将其视为地图,则需要非常小心:

new Properties(defaultProperties);

这经常会引起人们的注意,因为它看起来像一个复制构造函数,但事实并非如此。如果您使用该构造函数,然后调用类似keySet() 的东西(继承自其Hashtable 超类),您将得到一个空集,因为PropertiesMap 方法不考虑默认@ 987654330@ 传递给构造函数的对象。只有使用Properties 本身定义的方法(例如getPropertypropertyNames 等)时,才会识别默认值。

所以如果需要合并两个 Properties 对象,这样做比较安全:

Properties merged = new Properties();
merged.putAll(properties1);
merged.putAll(properties2);

这将为您提供更可预测的结果,而不是任意将其中一个标记为“默认”属性集。

通常,我建议不要将 Properties 视为 Map,因为(在我看来)这是 Java 早期的一个实现错误(属性应该包含 Hashtable,而不是扩展它 -那是懒惰的设计),但Properties 中定义的贫血接口本身并没有给我们很多选择。

【讨论】:

  • 将 Properties 视为 Map 的另一个危险是它没有“泛化”:properties.put("key", new Object()) 将编译。
  • 它会编译,是的,并且在某些情况下它会正常工作,只要您再次使用get() 将其取出,并且不要尝试使用getProperty() 检索它。
  • 这里还有一个有价值的信息:对于属性,始终使用setProperty()getProperty()。对吗?
  • 为了安全起见,是的,但如果您确定自己知道自己在输入什么,则可以使用 get()put()
  • 这对我帮助很大!请注意,属性的实现类似于责任链,但 #get()#put() 没有被覆盖,因此要使用责任链功能(从上层处理程序读取值),您必须使用 #getProperty()。恕我直言,继承 HashMap 而不覆盖 #get()/#set()(和其他)可能不是最好的设计决策。
【解决方案2】:

假设您最终想从文件中读取属性,我会在同一个属性对象中加载两个文件,例如:

Properties properties = new Properties();
properties.load(getClass().getResourceAsStream("default.properties"));
properties.load(getClass().getResourceAsStream("custom.properties"));

【讨论】:

    【解决方案3】:

    你差不多好了:

    Properties defaultProperties = new Properties();
    defaultProperties.setProperty("key1", "value1");
    defaultProperties.setProperty("key2", "value2");
    
    Properties finalProperties = new Properties(defaultProperties);
    finalProperties.setProperty("key2", "value3");
    

    编辑:put替换为setProperty

    【讨论】:

      【解决方案4】:

      是的,你是对的,只需调用 putAll 方法就可以了。

      【讨论】:

      • CW 避免发生冲突,即使这是我即将给出的答案
      【解决方案5】:

      putAll(): 将所有映射从指定映射复制到此哈希表。这些映射将替换此哈希表对当前指定映射中的任何键的任何映射。

      Properties merged = new Properties();
      merged.putAll(properties1);
      merged.putAll(properties2);
      

      第 2 行完全没有效果。第一个文件中的所有属性都不会在合并的属性对象中。

      【讨论】:

      • 你的最后一行完全不真实。 properties1 中所有未出现在 properties2 中的属性将在合并中设置为 properties1 中的值。
      猜你喜欢
      • 2013-04-08
      • 1970-01-01
      • 2019-06-19
      • 2022-01-04
      • 2011-03-19
      • 1970-01-01
      • 2019-10-08
      相关资源
      最近更新 更多