【问题标题】:Constants vs properties in javajava中的常量与属性
【发布时间】:2017-04-28 07:55:43
【问题描述】:

在我的 java 程序中声明常量值的最佳方法应该是什么?

这是在 .properties 文件中声明常量值还是在不同的类中将该值声明为静态最终值的最佳方法?

【问题讨论】:

  • 问题是,是否应该在未来更新该值(也要考虑错误修复)。如果答案是肯定的,这是一个属性。如果不是,这是一个常数。
  • @AxelH 不一定。如果您必须修复错误的常量,则需要部署新代码。请参阅我关于这方面的回答 ;-)
  • @GhostCat 这就是我在此过程中包含错误修复的原因。这意味着常量不应该是错误的来源(我知道,这是一个很长的希望;))。
  • 不过,很好的问题,值得深思。仅作记录:一旦您达到支持水平,也许您会发现其他值得支持的答案;-)

标签: java properties constants


【解决方案1】:

问题的答案取决于您想要完成什么。但其中也有误会。

属性文件

属性文件并不意味着可以替代或替代常量。它们用于存储可配置的值,例如 ip、语言等。从文件加载常量会破坏常量的用途。

常量

另外一点是public static final变量在java中不是一个好方法,首选的方法是使用枚举器。(来自Effective Java, Item 30: Use enums instead of int constatns)。 enum 将迫使您以有意义的方式对常量进行分组,而充满随机 public 常量的类很难管理。 Enum 使您能够提供功能,例如检查、验证、将常量与多个对象相关联,并且可以在 switch 语句中使用。 Enums 也被编译,这使得它们更高效和类型安全。这本书更详细地解释了enums 的好处。

我认为最好的方法是考虑该值是否会根据某些外部因素而改变,或者它是否始终保持不变。

属性文件和对配置的全局访问

假设您的属性文件中有一个 ip,并且您希望能够从代码中的任何位置访问该值。您可以只读取该值并将其加载到公共静态最终变量中。

如果你这样做,你将如何控制值被初始化,或者配置的值是正确的?那么在这种情况下,您可以使用单例类模式(只能存在该类的一个实例),它会加载文件并检查值是否正确。

它可以将值存储在private static final 变量中,并启用可以执行所需检查以确保值正确的getter。这使您可以全局访问变量并将逻辑分组在一个地方。

下次您向文件添加值时,您只需要更新这个类,而不需要在代码中搜索它所在的位置以及检查是否正确。

注意

很多人都在说,做某事并没有真正的“最佳方式”。我认为这是真的,但如果你能接触到 Joshua BlochEffetive Java 等书籍,你应该阅读它们并向那些为真的很久了。

【讨论】:

    【解决方案2】:

    如果这些值不是环境值,即dev,qa,stage 特定的并且在代码的整个生命周期中不会改变,请在代码中将它们声明为 static final。

    常量的缺点是你需要重新编译它们,如果你对它们做了一些改变,这在属性中不是这样,但如果它是一个常量,它根本不应该改变。

    例如:- 您在 dev/qa/stage/prod 环境中可能有不同的用户名“admin”凭据。

    然后您可以定义管理员用户,如public static final String userId="admin",但您想从属性文件中提供密码,并根据您运行代码的环境进行更改。

    喜欢

    dev.properties admin.password = 123456.

    qa.properties admin.password = abcdef.

    然后根据你的环境从属性文件中读取这些密码。

    【讨论】:

      【解决方案3】:

      真正的答案取决于您的要求。现实世界中没有“A 比 B 更好”。仅:“考虑到 x,y,z 的要求,A 比 B 更有帮助。

      因此,您只需考虑这两种方法的优缺点,以确定哪种方法对您“更好”。

      使用常量的优点:

      • 编译时安全
      • 首先支持编译器
      • 简单性:只有一个常数。属性需要来自文件,它们都是扁平字符串,甚至可以缺失

      常量的缺点:

      • 错误修复要求您向客户提供重新编译的类文件
      • 为了应用错误修复,需要停止运行您的代码的 JVM;或者至少需要重新部署您的容器(如 Tomcat 中的 WAR)。

      属性只是“反过来”。

      换句话说:如果您愿意,您可以编写大量复杂的代码,通过允许您重新读取属性信息来“修补”正在运行的应用程序。 通过这样做,您可以让您的客户修补正在运行的应用程序,方法是提供一个新的属性文件并在应用程序内触发一些“重新读取属性”挂钩。但请不要误会:实施正确、可靠的方法是困难

      但除非上述特性对您具有真正的价值,否则您很可能最好使用普通的编译时常量。您会看到,“部署更新”是将文件提供给客户。这些文件中有多少是类文件或属性文件并不重要(当我们不是在谈论“修补程序”要求时)。

      【讨论】:

        【解决方案4】:

        我已经尝试了这两种方法 - 文件和公共静态最终类,两者都可以工作。不过有几点需要注意:

        • 如果您的程序需要由想要更改这些常量的各方测试/运行,则在文件中声明将特别有利。在这种情况下,这些将被称为应用程序/程序的属性。 Spring 遵循这种方法进行配置。
        • 在一个类中声明它们将保证一次又一次地重新构建应用程序,但如果这些常量不改变或不需要被多方访问,您可以很容易地选择静态最终类方法。 Android 以 R.java 文件中动态生成的常量声明为例。 顺便说一句,这种方法可以将控制权保留在您的手中。使用您的代码的 3rs 方将无法更改这些常量。 文件方法将控制权交给其他人以更改它们。

        Object Mappers 也希望您在配置文件中有 Bean 属性,但在 Java Annotation 中,它介于两者之间并优雅地解决了它。

        【讨论】:

          【解决方案5】:

          还有第三个选项:系统属性。它们可以在用于启动程序的命令行中定义,您也可以使用常量来轻松访问它们并提供默认值。

          例子:

          public static final String HOSTNAME = System.getProperty("my.host-name", "localhost");
          

          但提供默认值并不总是一个好主意。

          话虽如此,您选择的方法将取决于问题的答案:是程序的值部分,还是安装程序的上下文的一部分。

          【讨论】:

            猜你喜欢
            • 2015-07-05
            • 1970-01-01
            • 2012-11-16
            • 2014-04-05
            • 1970-01-01
            • 2015-08-25
            • 1970-01-01
            • 1970-01-01
            • 2023-01-21
            相关资源
            最近更新 更多