当前位置:  开发笔记 > 编程语言 > 正文

在Java中实现常量的最佳方法是什么?

如何解决《在Java中实现常量的最佳方法是什么?》经验,为你挑选了12个好方法。

我见过这样的例子:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

并且假设我可以有一个Constants类来包装常量,声明它们是静态final.我几乎不知道Java,我想知道这是否是创建常量的最佳方法.



1> jjnguy..:

这是完全可以接受的,甚至可能是标准.

(public/private) static final TYPE NAME = VALUE;

TYPEtype 在哪里,NAME是带有下划线的所有大写字母的名称,VALUE是常量值;

我强烈建议不要将常量放在自己的类或接口中.

作为旁注:声明为final且可变的变量仍然可以更改; 但是,变量永远不能指向不同的对象.

例如:

public static final Point ORIGIN = new Point(0,0);

public static void main(String[] args){

    ORIGIN.x = 3;

}

这是合法的,ORIGIN然后是(3,0)点.


以前关于import static的评论仅适用于Java 5+.有些人认为速记不值得混淆,因为常量来自何处,当读取长代码时,MaxSeconds.MAX_SECONDS可能更容易跟随然后上升并查看导入.
你甚至可以'导入静态MaxSeconds.MAX_SECONDS;' 这样你就不必拼写MaxSeconds.MAX_SECONDS
如果你正在阅读这个问题,请仔细阅读下面的两个答案,然后再认真对待这个答案,尽管如果没有接受它会引起争议.
因为你可以像jjnguy所展示的那样改变objetc,最好是你的constatns是不可变对象或只是普通的原始/字符串.
@jjnguy你没有错,但如果我只阅读你的答案的问题和前几行,我会认为"一个常数类"是"完全可以接受的,甚至可能是标准".*那个*概念*是错误的.

2> MetroidFan20..:

我强烈建议不要有一个常量类.当时看起来似乎是一个好主意,但是当开发人员拒绝记录常量并且类增长到包含超过500个常量时,这些常量根本不相关(与应用程序的完全不同的方面有关),通常会变成完全不可读的常量文件.代替:

如果您可以访问Java 5+,请使用枚举来定义应用程序区域的特定常量.对于这些常量,应用程序区域的所有部分都应引用枚举,而不是常量值.您可以声明类似于声明类的枚举.枚举可能是Java 5+中最有用(也可以说是唯一)的有用功能.

如果您拥有仅对特定类或其子类之一有效的常量,请将它们声明为protected或public,并将它们放在层次结构中的顶级类中.这样,子类可以访问这些常量值(如果其他类通过public访问它们,则常量不仅对特定类有效...这意味着使用此常量的外部类可能与包含常量的类)

如果您有一个定义了行为的接口,但返回的值或参数值应该是特定的,那么在该接口上定义常量是完全可以接受的,这样其他实现者就可以访问它们.但是,避免创建一个仅用于保存常量的接口:它可能变得像为保持常量而创建的类一样糟糕.


关闭主题,但是......泛型当然不是很完美,但我认为你可以为它们提供一个非常好的案例,因为它们是Java 5的有用功能:)
完全同意......这可以记录为大型项目的经典反模式.
@ŁukaszL.这个问题本身就是基于意见的(每当"最佳"出现时,通常都是意见问题),所以答案是这个问题的有效答案.我已经给出了答案(是的,我*相信*是,所以是的,这是一种意见,因为再次"最佳"随时间变化并且通常基于意见)在Java中实现常量的最佳方法是.

3> Marcio Aguia..:

使用接口只是为了保持常量(由Josh Bloch 命名为常量接口模式)是一个不好的做法.这是Josh建议的:

如果常量与现有类或接口紧密相关,则应将它们添加到类或接口.例如,所有盒装数字基本类(如Integer和Double)都会导出MIN_VALUE和MAX_VALUE常量.如果常量最好被视为枚举类型的成员,则应使用枚举 类型导出它们.否则,您应该使用不可实例化的实用程序类导出常量.

例:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

关于命名约定:

按照惯例,这些字段的名称由大写字母组成,单词由下划线分隔.这些字段包含原始值或对不可变对象的引用至关重要.


如果你打算做一些不好的练习,或许你应该解释为什么你认为它是?
这是一个老帖子,但最好使用`abstract`表示法而不是私有构造函数.
@XtremeBiker标记类`abstract`而不是私有构造函数并不能完全阻止实例化,因为可以将它子类化并实例化子类(不是这样做是个好主意,但它是可能的).@ToolmakerSteve你不能使用私有构造函数对类进行子类化(至少不会没有严重的错误),因为子类的构造函数需要调用其超类的(现在是私有的)构造函数.因此,将其标记为"final"是不必要的(但可能更明确).
马特,虽然骑车人的建议不是假的,但我会主张最后的课程,而不是抽象的课程.骑车者的观点是,你要确保你的常数类不可改变.因此,通过将其标记为final,您不允许对其进行子类化或实例化.这也有助于封装其静态功能,并且不允许其他开发人员对其进行子类化并使其执行不设计的操作.
使用类只是为了保持常量更糟糕.如果您从不想创建该类的对象,为什么首先使用常规**类**?
要强制执行不可实例化的类,最好在私有构造函数中抛出新的AssertionError();`以确保它不通过反射实例化.

4> 小智..:

在Effective Java(第2版)中,建议您使用枚举而不是静态整数来表示常量.

这里有关于Java的枚举的好文章:http: //java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

请注意,在该文章的最后提出的问题是:

那么什么时候应该使用枚举?

答案是:

任何时候你需要一组固定的常量



5> 小智..:

只是避免使用界面:

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

这很诱人,但是违反了封装并模糊了类定义的区别.



6> albus.ua..:

我使用以下方法:

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用来保持不变.对我来说,它看起来更"面向对象".


有趣,但繁琐.为什么不按照其他人的建议在与他们关系最密切的类中创建常量呢?例如,在其他地方的数据库代码中,您是否有连接的基类?例如"ConnectionBase".然后你可以把常量放在那里.任何使用连接的代码都可能已经有一个导入,只能说"ConnectionBase.URL"而不是"Constants.DB.Connection.URL".
@ToolmakerSteve但是多个类可以使用的常规常量呢?例如,样式,Web服务URL等...?

7> Kevin Day..:

在单独的类中创建静态最终常量可能会让您遇到麻烦.Java编译器实际上会对此进行优化,并将常量的实际值放入任何引用它的类中.

如果您稍后更改了"常量"类,并且您没有对引用该类的其他类进行硬重新编译,那么最终将使用旧值和新值的组合.

不要将它们视为常量,而应将它们视为配置参数并创建一个类来管理它们.这些值是非最终的,甚至考虑使用getter.将来,当您确定某些参数实际上应该由用户或管理员配置时,它将更容易实现.



8> Yann Ramin..:

您可以犯的第一个错误是创建一个全局可访问的类,使用通用名称调用,如常量.这简直就是乱七八糟的垃圾,你失去了弄清楚系统中哪些部分使用这些常量的能力.

相反,常量应该进入"拥有"它们的类.你有一个名为TIMEOUT的常量吗?它可能应该进入您的Communications()或Connection()类.MAX_BAD_LOGINS_PER_HOUR?进入User().等等等等.

另一种可能的用途是Java .properties文件,当"常量"可以在运行时定义,但不容易用户更改.您可以将它们打包在.jars中,并使用Class resourceLoader引用它们.



9> Jason Cohen..:

这是正确的方法.

通常,常量不会保存在单独的"常量"类中,因为它们不可发现.如果常量与当前类相关,那么将它们保留在那里有助于下一个开发人员.



10> Sébastien D...:

枚举怎么样?



11> 小智..:

我同意使用界面不是要走的路.在Bloch的Effective Java中,避免这种模式甚至有自己的项目(#18).

Bloch对常量接口模式的一个参数是使用常量是一个实现细节,但实现一个接口来使用它们会在导出的API中公开该实现细节.

public|private static final TYPE NAME = VALUE;模式是声明常量的好方法.就个人而言,我认为最好避免单独设置一个容纳你所有常数的课程,但除了个人偏好和风格外,我从未见过不这样做的理由.

如果您的常量可以作为枚举进行良好建模,请考虑1.5或更高版本中可用的枚举结构.

如果您使用的是1.5之前的版本,则仍然可以使用普通的Java类来提取类型安全枚举.(有关详细信息,请参阅此网站).



12> 小智..:

我更喜欢使用getter而不是常量.那些getter可能会返回常量值,例如public int getMaxConnections() {return 10;},但是任何需要常量的东西都会经过一个getter.

一个好处是,如果你的程序超出常量 - 你发现它需要是可配置的 - 你可以改变getter返回常量的方式.

另一个好处是,为了修改常量,您不必重新编译使用它的所有内容.当您引用静态final字段时,该常量的值将编译为引用它的任何字节码.


好的重新编译引用类在21世纪几乎不是负担.并且你永远不应该使用accessor/mutator(getter/setter)模型来处理*其他*而不是访问和变异成员变量.常量在概念上意味着在本质上是立即的,而吸气剂/制定者(两者)意味着管理**状态**.此外,你只是要求混淆:人们不会指望一个吸气剂只能产生恒定.
推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有