对 BigDecimal 常量使用 Java 枚举
Using Java Enum for BigDecimal Constants
原来我有一个 class 有一堆私人静态决赛
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");
...
以及 class 中使用这些常量的一系列方法
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);
}
现在我想创建其他使用相同常量的类似 classes。起初我扩展了一个包含这些常量的基础 class 但后来由于其他问题决定尝试组合而不是继承,现在我正在尝试将 Enum 用于我的常量。
public enum EnumBD {
BD_0_00 (new BigDecimal("0.00")),
BD_0_02 (new BigDecimal("0.02")),
BD_0_03 (new BigDecimal("0.03")),
BD_0_04 (new BigDecimal("0.04")),
BD_0_05 (new BigDecimal("0.05")),
.....
private BigDecimal value;
private EnumBD(BigDecimal value) {
this.value = value;
}
public BigDecimal getValue() {
return value;
}
}
但在我的方法中,我对所有常量的引用来自这样的东西
setLength_tolerance_max(BD_0_02);
至此
setLength_tolerance_max(EnumBD.BD_0_02.getValue());
我是不是跑偏了,或者这就是 Enum 常量的用途?
在这种情况下不会使用枚举,除非有更多描述这些值的数据。
一种首选的做事方式是使它们成为全球性的,I.E. public static final
。由于 BigDecimal
是 不可变的 ,您不必担心一般的 "no global state" 规则。它们基本上成为常量。
枚举似乎让您能够将键值对移出到另一个结构,该结构清理了使用此组合的 class。这也可以通过创建一个 class 来实现,它具有 public 属性,例如 BD_0_00... Enum 确实不会为您带来太多实施。
Now I'd like to create other similar classes that use the same
constants. At first I extended a based class that contained these
constants but then decided to try composition instead of inheritance
because of other issues and now I'm trying to use Enum for my
constants.
一般来说,有两种方法(除了定义您自己的枚举 class 之外)导出常量以供多个 classes 使用。也就是说,您真的应该考虑是否有一种可行的方法来使用枚举 class 来表示您的常量,因为枚举 class 是您拥有一组固定常量时可以选择使用的工具在编译时已知。以下是您决定不使用枚举 class.
的情况
- 使用界面
此建议是有保留的。这种机制作为导出常量的一种方式工作,但它被编码专家视为一种反模式,而不是要模仿的模式,尤其是在您导出的 API 中。
尽管如此,如果您在接口中定义静态最终常量,那么实现该接口的任何 class(以及该 class 的任何子class)都将能够通过不合格的名称使用您的常量。以这种方式仅定义常量的接口称为常量接口。 Java 平台库中有一些常量接口示例。
不使用常量接口的原因有很多,并且已经在别处讨论过……但是它们使用起来很方便。以您自己的特权使用常量接口,并注意它们有可能导致问题(命名空间污染、程序员混淆等)。
- 使用一个class
将您的常量定义为 public、final 和普通 class 中的静态常量。它们很可能也应该是原始类型或不可变类型。然后,您的 class 可以将这些常量导出到可以使用它们的任何其他 class。
这优于使用常量接口导出常量,因为接口实际上只应用于定义类型和 APIs。 Non-instantiable "constant classes" 是对 class 机制的完全可接受的使用。如果常量与主题相关,则尤其如此。例如,假设您希望定义表示各种沸点的常量:
public class BoilingPoints {
public static final double WATER = 100.0;
:
:
public static final double ETHANOL = 86.2;
private BoilingPoints() { throw new AssertionError(); }
}
请注意,构造函数确保 class 是 non-instantiable。
主要缺点是您通常必须使用 class 名称限定从 class 导出的常量。由于 static
import
机制已添加到该语言中,如果您不想这样做,则不必这样做。
当您需要可读性和便利性时,您想使用常量,例如
static final double PI = 3.1415;
让你写出类似
的东西
c = 2 * PI * r;
明确意图。当你想确保你的值来自 pre-defined set and 在编译时完成检查时,枚举很有用。假设我想写一个 class 模拟交通灯之类的东西。我可以为其状态定义一个枚举,STOP
、CAUTION
和 GO
。这样,我可以在编译时确保我的灯光状态的任何设置都是这三种状态之一。如果我为这些定义了整数常量,没有什么可以阻止有人不使用我的常量并简单地将状态设置为 139。
将值与我的 Enum 元素相关联的能力是一个额外的便利,例如,在我的交通灯案例中,我可以将 RGB 值与每个元素相关联以用于显示目的。
在您的情况下,常量似乎相当明确,而枚举只会使您的代码复杂化。
原来我有一个 class 有一堆私人静态决赛
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");
...
以及 class 中使用这些常量的一系列方法
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);
}
现在我想创建其他使用相同常量的类似 classes。起初我扩展了一个包含这些常量的基础 class 但后来由于其他问题决定尝试组合而不是继承,现在我正在尝试将 Enum 用于我的常量。
public enum EnumBD {
BD_0_00 (new BigDecimal("0.00")),
BD_0_02 (new BigDecimal("0.02")),
BD_0_03 (new BigDecimal("0.03")),
BD_0_04 (new BigDecimal("0.04")),
BD_0_05 (new BigDecimal("0.05")),
.....
private BigDecimal value;
private EnumBD(BigDecimal value) {
this.value = value;
}
public BigDecimal getValue() {
return value;
}
}
但在我的方法中,我对所有常量的引用来自这样的东西
setLength_tolerance_max(BD_0_02);
至此
setLength_tolerance_max(EnumBD.BD_0_02.getValue());
我是不是跑偏了,或者这就是 Enum 常量的用途?
在这种情况下不会使用枚举,除非有更多描述这些值的数据。
一种首选的做事方式是使它们成为全球性的,I.E. public static final
。由于 BigDecimal
是 不可变的 ,您不必担心一般的 "no global state" 规则。它们基本上成为常量。
枚举似乎让您能够将键值对移出到另一个结构,该结构清理了使用此组合的 class。这也可以通过创建一个 class 来实现,它具有 public 属性,例如 BD_0_00... Enum 确实不会为您带来太多实施。
Now I'd like to create other similar classes that use the same constants. At first I extended a based class that contained these constants but then decided to try composition instead of inheritance because of other issues and now I'm trying to use Enum for my constants.
一般来说,有两种方法(除了定义您自己的枚举 class 之外)导出常量以供多个 classes 使用。也就是说,您真的应该考虑是否有一种可行的方法来使用枚举 class 来表示您的常量,因为枚举 class 是您拥有一组固定常量时可以选择使用的工具在编译时已知。以下是您决定不使用枚举 class.
的情况- 使用界面
此建议是有保留的。这种机制作为导出常量的一种方式工作,但它被编码专家视为一种反模式,而不是要模仿的模式,尤其是在您导出的 API 中。
尽管如此,如果您在接口中定义静态最终常量,那么实现该接口的任何 class(以及该 class 的任何子class)都将能够通过不合格的名称使用您的常量。以这种方式仅定义常量的接口称为常量接口。 Java 平台库中有一些常量接口示例。
不使用常量接口的原因有很多,并且已经在别处讨论过……但是它们使用起来很方便。以您自己的特权使用常量接口,并注意它们有可能导致问题(命名空间污染、程序员混淆等)。
- 使用一个class
将您的常量定义为 public、final 和普通 class 中的静态常量。它们很可能也应该是原始类型或不可变类型。然后,您的 class 可以将这些常量导出到可以使用它们的任何其他 class。
这优于使用常量接口导出常量,因为接口实际上只应用于定义类型和 APIs。 Non-instantiable "constant classes" 是对 class 机制的完全可接受的使用。如果常量与主题相关,则尤其如此。例如,假设您希望定义表示各种沸点的常量:
public class BoilingPoints {
public static final double WATER = 100.0;
:
:
public static final double ETHANOL = 86.2;
private BoilingPoints() { throw new AssertionError(); }
}
请注意,构造函数确保 class 是 non-instantiable。
主要缺点是您通常必须使用 class 名称限定从 class 导出的常量。由于 static
import
机制已添加到该语言中,如果您不想这样做,则不必这样做。
当您需要可读性和便利性时,您想使用常量,例如
static final double PI = 3.1415;
让你写出类似
的东西c = 2 * PI * r;
明确意图。当你想确保你的值来自 pre-defined set and 在编译时完成检查时,枚举很有用。假设我想写一个 class 模拟交通灯之类的东西。我可以为其状态定义一个枚举,STOP
、CAUTION
和 GO
。这样,我可以在编译时确保我的灯光状态的任何设置都是这三种状态之一。如果我为这些定义了整数常量,没有什么可以阻止有人不使用我的常量并简单地将状态设置为 139。
将值与我的 Enum 元素相关联的能力是一个额外的便利,例如,在我的交通灯案例中,我可以将 RGB 值与每个元素相关联以用于显示目的。
在您的情况下,常量似乎相当明确,而枚举只会使您的代码复杂化。