Java:使用属性文件中的键名而不使用硬编码字符串作为键

时间:2013-07-18 00:09:33

标签: java properties configuration hard-coding

问题陈述

我有一个在我的java项目中访问的属性文件。

我的.properties文件的示例内容:

appName=MyApp
appType=TypeA

假设我在整个java项目中访问单个属性appName

props.getProperty("appName");

我不想遍历属性文件来获取属性值;我只是从属性文件中获取单个属性值。但我不喜欢我必须使用硬编码字符串访问该属性的事实,因为它可能导致维护问题(即更改硬编码字符串的所有实例)。

我目前的做法

在我目前的方法中,我有一个实用程序类,它创建表示属性文件中的键名的静态最终变量,然后我使用该变量来访问属性值:

public static final String APP_NAME = "appName";
...
props.getProperty(APP_NAME);

但这看起来有点过分,因为它是多余的,并且仍然是潜在的维护问题。密钥已存在于属性文件中,我在我的实用程序类中再次声明它们。

使用get方法访问属性值时,是否有更“免维护”的方式访问代码中的键名?

3 个答案:

答案 0 :(得分:3)

不,你做得对。它实际上相当免维护。

使用Java Enums会稍微好一点 - 即

public class PropertiesWrapper {
   private final Properties props;
   ...
   public String get(MyEnum key) {  return props.get(key.toString());
}

原因是,即使你将String变为常量,也不能在不重新编译使用常量的所有代码的情况下更改它 - 因为编译器会在编译时用“appName”替换常量。

如果你使用枚举并删除枚举常量,代码仍然需要重新编译,但是当它实际上现在要求错误时它似乎不会很好。此外,通过使用toString()代替name()来获取属性名称,您可以在枚举中覆盖toString()以返回与常量名称不同的内容。

使用枚举的缺点是系统无法在没有其他方法访问Properties的情况下查找编译时未知的任何内容。

答案 1 :(得分:1)

可能有一个库会读取属性文件并将其生成到带有getter的源文件中。然后,您必须使用您的代码编译该源文件。那将是一个非常漂亮的图书馆。但是,如果这不存在,我认为没有其他办法可以做到这一点。

即使它存在,我也看不出它如何能够知道key1Stringkey2Integer。你可能仍然需要在某处施放。那,或者维护一个单独的元数据文件,然后你又回到了更多的维护。

问题是,您可以随时更改属性文件密钥,编译器无法知道您是否已执行此操作。

我能给你的最好的是用于阅读配置文件的库。查看Apache Configuration library

答案 2 :(得分:0)

一位同事和我目前正面临着一个非常相似的问题,我们做了一些研究,看看是否可以通过反思解决这个问题。不幸的是,我们没有设法解决它,但我会尝试详细说明我们的问题和策略。也许聪明的人可以使用我们的基线来构建一些克服了让我们回归的局限的东西。

问题陈述:我们想要读取属性文件中的值,并将这些值分配给Java对象(设置对象)中的字段。键名对我们来说无关紧要,因此最好只使用Java字段的名称作为键名。

这将带来两大好处:

  1. 首先,它允许我们删除大量冗余字符串常量。
  2. 其次,它允许我们在一个地方定义字段分配,因为我们的设置类是使用继承实现的。
  3. 我们计划在超类中定义一个方法,该方法将使用反射来获取所有实例字段。从这里开始,我们的策略是遍历所有领域并且:

    1. 获取该字段的名称,
    2. 使用此名称在属性文件中查找属性
    3. 获取字段的类型,并使用此类型转换从属性文件中读取的字符串值,然后将其分配给当前字段。
    4. 使用这种方法,只需添加一个新的实例字段即可添加新属性。不需要额外的代码来阅读或写新属性。

      不幸的是,由于两个问题,这是不可行的:

      1. Java编译器可以删除有关字段名称的信息,请参阅this answer
      2. 根据JVM,使用Class#getDeclaredFields()可能会拒绝访问。