Java 中带有约束的双精度数?

问题描述 投票:0回答:4

我正在将旧版 Python 系统移植到 Java。我主要是一名 Python 开发人员,所以这个问题涉及我如何在原始 Python 系统中采用不满意的模式,但在我的 Java 版本中做得更好。

我正在开发的一个系统涉及产品价格。所有产品的价格都 > 0.0.

在原始系统中,所有价格都表示为 Python 浮点对象(大致类似于 Java Double)。对这些价格进行操作的函数通常以一堆断言开始,以检查价格范围是否合理。由于有很多函数,所以有很多断言,一段时间后就会变得非常重复。

这些断言总比没有好,但最好在某些东西试图创造负价格时立即抛出错误,因为这就是错误所在。

我突然想到,通过发明一种新的数字类型,我的重新实现可能会做得更好,它的行为在所有方面都与 Double 完全相同,只是它不能用负值构造。如果我有这样一个对象,那么我可以依赖 Java 的类型系统,而不需要编写那么多断言。

除此之外(首先)它将遵守算术的所有正常规则 - 它将是 Double 的子类。

稍后我可能会通过添加包含更多现实世界货币特征的功能来扩展此类,例如防止零钱。这在我的初始版本中实际上并不需要,但我希望我采用的任何模式都能在接下来的几个月内适应这种开发。

这种模式对于 Java 开发人员来说是否可以接受?有没有更好的方法来保留类似数字对象的灵活性,但对其可能值进行限制?

java
4个回答
5
投票

首先,由于不精确,没有真正的处理金钱的软件使用浮点数学。请参阅维基百科页面上有关浮点运算的准确性问题部分。保存整数便士的“Money”类是处理此问题的一种常见方法。

其次,是的,对于这样的类来说,拥有一个通过抛出异常来拒绝负数的构造函数将是一件好事。

这是 Dobb 博士的期刊上关于该主题的一篇很好的文章,并附有代码。


1
投票

这是一个合理的想法(除了使用 Double 之外)。 你不能扩展 Double 因为它是最后一个类。 无论如何,您应该使用 BigDecimal 而不是 Double (正如@Jagger 在 OP 评论中提到的那样)。 但是,您可能最好创建自己的 Price 类并在内部维护 BigDecimal,因为这将使您更好地控制该值的使用方式..


1
投票

是的,这确实不仅可以接受,而且是 Java 开发人员要做的第一件事。 但有一个例外:请勿使用浮点数或双倍来表示货币价值

我建议:

  • 您使用要实现的所有方法创建一个接口。
  • 可能是一个抽象基类,它不是 BigDecimal 的子类,但使用 BigDecimal 的私有值(没有子类化,而是委托模式)
  • 您创建的最终类实现了所有货币功能、断言和保障措施。

1
投票

首先,是的,子类化某物或为此编写一个类是可以接受的,并且有人这样做,但你不能,但是,子类化

java.lang.Double
,这是一个
final
类。抛出构造函数远不及 C++ 或其他语言中那样的灾难。

其次,你不应该将其存储在

double
中,除非你确实需要几分钱,而你刚刚说过你不需要。整数类会是一个更好的主意。

第三,我建议子类化

java.lang.Number
以获得自动装箱的所有好处。

© www.soinside.com 2019 - 2024. All rights reserved.