【问题标题】:How to implement Constants in Java [duplicate]如何在 Java 中实现常量 [重复]
【发布时间】:2012-02-07 05:59:53
【问题描述】:

这是一个好主意吗,将Constants类容器内的类中的常量分组,如

public final class Constants {
  public final class File {
    public static final int MIN_ROWS = 1;
    public static final int MAX_ROWS = 1000;

    private File() {}
  }

  public final class DB {
    public static final String name = "oups";

    public final class Connection() {
      public static final String URL = "jdbc:tra-ta-ta";
      public static final String USER = "testUser";
      public static final String PASSWORD = "testPassword";

      private Connection() {}
    }

    private DB() {}
  }

  private Constants() {}
}

它允许使用Constants.DB.Connection.URL 代替DbConnectionConstants.URL

【问题讨论】:

  • 分组有时有助于清晰。 public class Constants { private static final class KeyOffsets { public static final int QTY = 0; //8-bytes (long) public static final int PRICE = 8; //8-bytes (long) } public static class Offset { public static final int Action = 16; } }
  • 因为我不喜欢我的代码对我大喊也不喜欢用 COBOL 编程,所以我倾向于使用 PascalCase 作为我的常量!!!!!!!

标签: java constants


【解决方案1】:

我通常更喜欢将常量放在它们所属的类中。例如,文件常量可能在使用它们的FileManager(或类似的东西)中。连接常量可能在您的 DBUtil 类中,它们会在其中使用。

想想 JDK。它有一个巨大的常量类吗?不。BorderLayout 使用(和一起使用)的常量在类BorderLayout 中。 JOptionPane 使用(和一起使用)的常量在JOptionPane 中。

【讨论】:

  • 如果一个常量在一个集中的地方只使用一次,我同意这种做法。但是,它可能不适用于更复杂的实现。
【解决方案2】:

优点:

  1. 你会得到一个很好的“路径”到你的常量。
  2. 如果同事遵循指导,您可能会得到一个跨代码常量约定。

缺点:

  1. 由于有许多常量和许多常量“域”,该类可能会变得过于繁琐而无法处理。
  2. 它不直观。它让我想起了 Ant 属性,而不是 java 常量。
  3. 它可以防止您的代码模块化。假设您要将 DB 连接包和文件处理包分离到不同的 jar 中,这些 jar 可能会被不同的应用程序使用。提供带有文件处理常量的数据库管理 jar 是多余的。而且您可以轻松获得许多这样的模块。

总之,当您只为自己编写一些小应用程序时,这可能会很方便。一般来说,这不是一个好习惯。

【讨论】:

    【解决方案3】:

    使用枚举http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

    每个 JVM 将只有一个枚举对象的副本

    【讨论】:

    • 如何在枚举中存储数据库服务器密码?
    • INSTANCE;public final PASSWORD="abcd";
    • 即使这样可行,这也是对enum 的滥用。此外,您的论点表明常量 Strings 并没有被 JVM 实习,它们是。
    • 你是对的。 String 对象只有一个副本。使用枚举只是封装事物的一种方式。您如何看待使用枚举作为实现单例模式的一种方式?你认为这是滥用用法吗?
    【解决方案4】:

    您始终可以使用foo.bar.baz 表示法在类路径中使用.properties 文件。这将使更改值更容易而无需重新编译。 Spring 框架提供实用程序来帮助动态刷新值。

    不过,我同意 @JB Nizet@yair 的观点,即保持与常量最相关的 Class 是一个更好的主意。

    【讨论】:

      【解决方案5】:

      您也可以将abstract 用于常量类,甚至比私有构造函数更好。如果您使用一个接口,它可以在类层次结构之外使用,并且可以简单地使用implements,尽管隐藏了来源(接口名称)。

      虽然有一个问题。如果您仅为常量导入类,编译器可能会删除 .class 中的导入并填充常量本身。如果以后更改常量的值,使用类将不会自动重新编译,并保持旧值。

      【讨论】:

      • 常量接口(或抽象类)通常被认为是一种反模式。引入了静态导入以在没有反模式的情况下具有相同的优势。您对进口的评论根本没有意义。导入仅在编译时使用。它们不在类文件中。无论您是否导入,常量始终是内联的。
      • @JBNizet yes interface 是一种反模式,因此 “虽然隐藏了来源。”imports 上:导入的类名正常出现在编译类的常量池中;对于上述情况并非如此。但同意,我会称之为编译器特定的错误。
      猜你喜欢
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 2019-02-25
      • 2016-05-19
      • 2010-09-12
      • 2016-09-12
      相关资源
      最近更新 更多