65

正如大多数人现在痛苦地意识到的那样,用于处理日历日期(特别是类java.util.Datejava.util.Calendar)的 Java API 是一团糟。

在我的头顶上:

  • 日期是可变的
  • Date 表示时间戳,而不是日期
  • 没有简单的方法在日期组件(日、月、年...)和日期之间进行转换
  • 日历使用起来很笨拙,并试图将不同的日历系统组合到一个类中

这篇文章总结得很好,JSR-310也解释了这些问题。

现在我的问题是:

这些类是如何进入 Java SDK 的?大多数这些问题看起来都相当明显(尤其是 Date 是可变的)并且应该很容易避免。那么它是怎么发生的呢?时间压力?还是只是回想起来问题很明显?

我意识到这不是一个严格的编程问题,但我会发现了解 API 设计如何会出错很有趣。毕竟,错误总是一个很好的学习机会(我很好奇)。

4

4 回答 4

45

有人说得比我说得更好:

  • Date表示特定的时间瞬间,精度为毫秒。这个类的设计是一个非常糟糕的笑话——即使是优秀的程序员也会搞砸的一个发人深省的例子。Date 中的大多数方法现在已被弃用,取而代之的是以下类中的方法。
  • Calendar是一个抽象类,用于在Date 对象和一组整数字段(例如年、月、日和小时)之间进行转换。

  • Class是JDKGregorianCalendar中唯一的子类。Calendar它为常用的日历系统进行日期到字段的转换。Sun 从 Taligent 获得了这种过度设计的垃圾软件的许可——这是普通程序员如何搞砸的一个发人深省的例子。

来自Java Programmers FAQ,版本来自 07.X.1998,作者 Peter van der Linden - 虽然这部分已从更高版本中删除。

至于可变性,许多早期的 JDK 类都受到它的影响(Point, Rectangle, Dimension, ...)。误导优化,我听说过一些人说。

这个想法是您希望能够重用对象(o.getPosition().x += 5)而不是创建副本(o.setPosition(o.getPosition().add(5, 0))),因为您必须对不可变对象进行操作。对于早期的 VM,这甚至可能是一个好主意,而对于现代 VM,这很可能不是。

于 2009-10-15T09:45:43.037 回答
21

Java 的早期 API 只不过是他们那个时代的产物。在那之后几年,不变性才成为一个流行的概念。您说不变性是“显而易见的”。现在可能是这样,但当时不是。就像依赖注入现在是“显而易见的”但不是 10 年前。

曾经创建 Calendar 对象也很昂贵。

出于向后兼容性的原因,它们保持这种状态。更不幸的是,一旦发现错误,旧类并没有被弃用,而是为所有 API 创建了新的日期/时间类。这在某种程度上发生在 JDK 8 采用 JodaTime 之类的 API ( java.time, JSR 310) 时,但实际上为时已晚。

于 2009-10-15T09:41:16.263 回答
9

时间本身并不容易衡量和处理。只需查看有关时间的维基百科文章的长度。然后,对于时间本身,也有不同的理解:绝对时间点(作为常数)、某个地点的时间点、时间范围、时间的分辨率……

我记得,当我第一次看到 java.util.Date(JDK 1.0?)时,我真的很高兴。我所知道的语言没有这样的功能。我没有考虑时间转换等。

我认为这是一团糟,因为如果您从一个理解级别(XMLGregorianCaldender 与日期)和需求(纳秒,2030 年过去)发展到更高级别,但保持旧的不变,那么所有变化都会留下一团糟。并且 java.util.Date 不是一个例外。只需看看 I/O 子系统或从 AWT 到 Swing 的过渡......

正因为如此,“我们有时应该按下重置按钮。” (谁说的,顺便说一句。?)

于 2009-10-15T11:38:13.737 回答
5

您可能会发现以下帖子很有趣。它几乎解释了 Calendar 类最初是如何进入 Java API 的,并阐明了 date 类的起源。

高度功能失调设计的七个习惯

于 2011-07-14T17:47:20.020 回答