对BigDecimal常量使用Java枚举

对BigDecimal常量使用Java枚举,java,constants,bigdecimal,Java,Constants,Bigdecimal,最初我有一节课,有很多私人的静态期末考试 private static final BigDecimal BD_0_06 = new BigDecimal("0.06"); private static final BigDecimal BD_0_08 = new BigDecimal("0.08"); private static final BigDecimal BD_0_10 = new BigDecimal("0.10"); private static final BigDecimal

最初我有一节课,有很多私人的静态期末考试

private static final BigDecimal BD_0_06 = new BigDecimal("0.06");
private static final BigDecimal BD_0_08 = new BigDecimal("0.08");
private static final BigDecimal BD_0_10 = new BigDecimal("0.10");
private static final BigDecimal BD_0_12 = new BigDecimal("0.12");
private static final BigDecimal BD_0_14 = new BigDecimal("0.14");
    ...
这个类中的一组方法使用了这些常量

private void computeFastenerLengthToleranceMax() {
        if (nominal_fastener_length.compareTo(BigDecimal.ONE) > 0 && nominal_fastener_length.compareTo(BD_TWO_AND_ONE_HALF) <= 0) {
            if (spec.getBasic_major_diameter().compareTo(BD_ONE_QUARTER) >= 0 && spec.getBasic_major_diameter().compareTo(BD_THREE_EIGTHS) <= 0) {
                setLength_tolerance_max(BD_0_02);
            }
            if (spec.getBasic_major_diameter().compareTo(BD_SEVEN_SIXTEENTHS) >= 0 && spec.getBasic_major_diameter().compareTo(BD_ONE_HALF) <= 0) {
                setLength_tolerance_max(BD_0_04);
            }
            if (spec.getBasic_major_diameter().compareTo(BD_NINE_SIXTEENTHS) >= 0 && spec.getBasic_major_diameter().compareTo(BD_THREE_QUARTER) <= 0) {
                setLength_tolerance_max(BD_0_06);
            }
}

但在我的方法中,我对所有常数的引用都是这样的

setLength_tolerance_max(BD_0_02);
对此

setLength_tolerance_max(EnumBD.BD_0_02.getValue());

我是否偏离了轨道,或者这就是枚举常量的使用方式?

在这种情况下不会使用枚举,除非有更多的数据描述这些值


一种更可取的做法是使其全球化,即
公共静态final
。由于
BigDecimal
不可变的,因此您不必担心一般的“无全局状态”规则。它们基本上变成常量。

似乎枚举可以让您将键值对移出到另一个结构中,从而清理利用此组合的类。这也可以通过创建一个具有公共属性(如BD_0_00)的类来实现。。。Enum并没有给您带来太多的好处

现在我想创建其他类似的类,它们使用相同的 常数。首先,我扩展了一个包含这些 但后来决定尝试组合而不是继承 因为其他问题,现在我正尝试使用Enum来 常数

基本上有两种方法(除了定义自己的枚举类之外),广义上讲,导出常量以在多个类中使用。也就是说,你真的应该考虑是否有一个可行的方法来使用EnUM类来表示常量,因为EnUM类是在编译时已知的一组固定常量时使用的工具。以下内容适用于您决定不使用枚举类的情况

  • 使用界面
这项建议是有保留的。这种机制可以作为导出常量的一种手段,但编码专家认为它是一种反模式,而不是要模拟的模式,尤其是在导出的API中

尽管如此,如果您在接口中定义静态最终常量,则实现该接口的任何类(以及该类的任何子类)都将能够通过其非限定名称使用您的常量。以这种方式仅定义常量的接口称为常量接口。Java平台库中有几个常量接口的示例

不使用常量接口的原因很多,在其他地方已经讨论过了。。。但是,它们可以方便地使用。按照自己的权限使用常量接口,并注意它们可能会导致问题(名称空间污染、程序员混乱等)

  • 使用类
在普通类中将常量定义为public、final和static。它们很可能也是基本类型或不可变类型。然后,您的类可以将这些常量导出到可以使用它们的任何其他类

这比使用常量接口导出常量更可取,因为接口实际上应该只用于定义类型和API。不可实例化的“常量类”是类机制的一种完全可以接受的用法。如果常数与主题相关,则尤其如此。例如,假设您希望定义表示各种沸点的常数:

public class BoilingPoints {
    public static final double WATER = 100.0;
    :
    :
    public static final double ETHANOL = 86.2;

    private BoilingPoints() { throw new AssertionError(); }
}
注意,构造函数确保类是不可实例化的


主要缺点是,通常必须使用类名限定从类导出的常量。由于
静态
导入
机制被添加到该语言中,如果您不想这样做,您不必这样做。

您希望在需要可读性和方便性时使用常量,例如

static final double PI = 3.1415;
让你写一些像

c = 2 * PI * r;
明确意图。当您希望确保值来自预定义集以及要在编译时执行的检查时,枚举非常有用。假设我想写一个类来模拟交通灯之类的东西。我可以为其状态定义枚举,
STOP
CAUTION
GO
。这样,我可以确保在编译时,我的光的状态的任何设置都是这三种状态之一。如果我为这些定义了整数常量,那么没有什么可以阻止某人不使用我的常量,而只是将状态设置为139

将值与枚举元素关联的功能是一种额外的便利,例如,在我的红绿灯情况下,我可以将RGB值与每个元素关联以用于显示目的


在您的情况下,似乎很清楚常量可以解决问题,枚举只会使代码复杂化

对我来说,这似乎不是枚举的正确用法。与
公共静态final
字段相比,您不会获得任何好处,这会使您的代码更加冗长。是的,因为枚举的主要目标是提供一组名称明确、类型明确的值,而不是命名一组大小数的方法。您最初的方法对于您的使用是合理的,您可以使用常量创建一个类,然后在需要的地方使用它们。你可以使用静态导入来保持简洁。是的,我觉得我的枚举方法有点不对劲。但是这篇文章和其他一些地方让我觉得我不应该使用constants类。@jeff这里的反对意见部分是关于存储在常量和枚举中的东西的类型。我在下面的回答中对此进行了详细阐述。您不需要枚举供您使用,常数就可以了,您可以轻松地将它们或多或少地放在任何您喜欢的地方。如果这些常数相互关联,则可以使用枚举来封装它们。还有一个字符串类型的额外属性也很好,我经常使用这种模式。“可能有意义,也可能没有意义”是这个问题的直接答案
c = 2 * PI * r;