为什么Java date API(java.util.Date,.Calendar)如此混乱?

时间:2009-10-15 09:34:06

标签: java date api-design

现在大多数人都非常清楚地意识到,用于处理日历日期的Java API(特别是类java.util.Datejava.util.Calendar)是一个糟糕的混乱。

脱离我的头顶:

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

This post总结得很好,JSR-310也解决了这些问题。

现在我的问题是:

这些类是如何进入Java SDK的?大多数这些问题看起来相当明显(特别是Date是可变的)并且应该很容易避免。那怎么回事?时间压力?或者回想起来的问题是否明显?

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

4 个答案:

答案 0 :(得分:42)

有人说它比我说的好:

  
      
  • Date表示特定时刻,以毫秒为单位   精确。这堂课的设计是一个非常糟糕的笑话 - 一个发人深省的   甚至优秀的程序员如何搞砸的例子。大部分方法都在   现在不推荐使用日期,替换为以下类中的方法。
  •   
  • Calendar是一个用于在Date之间进行转换的抽象类   对象和一组整数字段,例如年,月,日和小时。

  •   
  • GregorianCalendar是JDK中Calendar的唯一子类。   它执行日历系统的日期到字段转换   常用。 Sun从Taligent获得了这个过度工程的垃圾 - a   一个平均程序员如何搞砸的清醒示例。

  •   

来自 Java程序员常见问题,版本来自07.X.1998,作者Peter van der Linden - 虽然这部分已从更高版本中删除。

至于可变性,很多早期的JDK类都受到它的影响(PointRectangleDimension,...)。错误的优化,我听到有人说。

我们的想法是,您希望能够重用对象(o.getPosition().x += 5)而不是创建副本(o.setPosition(o.getPosition().add(5, 0))),因为您必须使用不可变项。对于早期的虚拟机,这甚至可能是一个好主意,而最有可能的不是现代虚拟机。

答案 1 :(得分:20)

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

创建Calendar对象的费用也很高。

出于向后兼容的原因,它们仍然是这样。或许更不幸的是,一旦错误得以实现,旧的类没有被弃用,并且为所有API提供了新的日期/时间类。这在某种程度上发生在JDK 8采用JodaTime之类的API(java.time,JSR 310),但实际上它太晚了。

答案 2 :(得分:8)

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

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

我认为这很糟糕,因为如果你从一个理解水平(XMLGregorianCaldender vs. Date)和需求(纳秒,过去2030年)发展到更高水平,但保持旧的不变,那么所有变化都会变得一团糟。并且java.util.Date不是Exception。只需看看I / O子系统或从AWT到Swing的转换......

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

答案 3 :(得分:5)

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

The Seven Habits of Highly Dysfunctional Design