为什么是 Java date API (java.util.Date, .日历)这么乱?

2022-08-31 15:14:28

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

在我的头顶上:

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

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

现在我的问题是:

这些类是如何进入Java SDK的?这些问题中的大多数似乎相当明显(特别是日期是可变的),应该很容易避免。那么它是如何发生的呢?时间压力?还是问题仅在回想起来就很明显?

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


答案 1

有人说得比我说得更好:

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

  • 类是 JDK 中唯一的子类。它为常用的日历系统执行日期到字段的转换。Sun从Taligent那里获得了这个过度设计的垃圾许可 - 这是一个发人深省的例子,说明普通程序员是如何搞砸的。GregorianCalendarCalendar

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

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

这个想法是,您希望能够重用对象(),而不是像创建不可变对象那样创建副本()。对于早期的 VM 来说,这甚至可能是一个好主意,而对于现代 VM 来说,这很可能不是一个好主意。o.getPosition().x += 5o.setPosition(o.getPosition().add(5, 0))


答案 2

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

创建日历对象也一度很昂贵。

出于向后兼容性的原因,它们保持这种状态。也许更不幸的是,一旦意识到错误,旧类就不会被弃用,并且会为所有未来的API创建新的日期/时间类。这在某种程度上发生在JDK 8采用像API(JSR 310)这样的JodaTime时,但实际上它太少太晚了。java.time