为什么 Java 日期 API (java.util.Date, .Calendar) 如此混乱?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1571265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is the Java date API (java.util.Date, .Calendar) such a mess?
提问by sleske
As most people are painfully aware of by now, the Java API for handling calendar dates (specifically the classes java.util.Dateand java.util.Calendar) are a terrible mess.
正如大多数人现在痛苦地意识到的那样,用于处理日历日期(特别是类java.util.Date和java.util.Calendar)的 Java API是一团糟。
Off the top of my head:
在我的头顶:
- Date is mutable
- Date represents a timestamp, not a date
- no easy way to convert between date components (day, month, year...) and Date
- Calendar is clunky to use, and tries to combine different calendar systems into one class
- 日期是可变的
- 日期代表时间戳,而不是日期
- 没有简单的方法可以在日期组件(日、月、年...)和日期之间进行转换
- Calendar 使用起来很笨拙,并试图将不同的日历系统组合成一个类
This postsums it up quite well, and JSR-310also expains these problems.
Now my question is:
现在我的问题是:
How did these classes make it into the Java SDK? Most of these problems seem fairly obvious (especially Date being mutable) and should have been easy to avoid. So how did it happen? Time pressure? Or are the problems obvious in retrospect only?
这些类是如何进入 Java SDK 的?大多数这些问题似乎相当明显(尤其是 Date 是可变的)并且应该很容易避免。那么它是如何发生的呢?时间压力?还是只有回过头来看问题才明显?
I realize this is not strictly a programming question, but I'd find it interesting to understand how API design could go so wrong. After all, mistakes are always a good learning opportunity (and I'm curious).
我意识到这不是严格的编程问题,但我发现了解 API 设计如何出错很有趣。毕竟,错误总是一个很好的学习机会(我很好奇)。
采纳答案by gustafc
Someone put it better than I could ever say it:
有人说得比我说得好:
- Class
Daterepresents a specific instant in time, with millisecond precision. The design of this class is a very bad joke - a sobering example of how even good programmers screw up. Most of the methods in Date are now deprecated, replaced by methods in the classes below.Class
Calendaris an abstract class for converting between aDateobject and a set of integer fields such as year, month, day, and hour.Class
GregorianCalendaris the only subclass ofCalendarin the JDK. It does the Date-to-fields conversions for the calendar system in common use. Sun licensed this overengineered junk from Taligent - a sobering example of how average programmers screw up.
- 类
Date代表特定的瞬间,精度为毫秒。这个类的设计是一个非常糟糕的笑话——一个发人深省的例子,说明即使是优秀的程序员也是如何搞砸的。Date 中的大多数方法现已弃用,取而代之的是以下类中的方法。Class
Calendar是一个抽象类,用于在Date对象和一组整数字段(例如年、月、日和小时)之间进行转换。Class
GregorianCalendar是CalendarJDK 中唯一的子类。它为常用的日历系统执行日期到字段的转换。Sun 从 Taligent 授权了这种过度设计的垃圾——这是普通程序员如何搞砸的一个发人深省的例子。
from Java Programmers FAQ, version from 07.X.1998, by Peter van der Linden - this part was removed from later versions though.
来自Java Programmers FAQ,版本从 07.X.1998 起,作者 Peter van der Linden - 不过这部分已从更高版本中删除。
As for mutability, a lot of the early JDK classes suffer from it (Point, Rectangle, Dimension, ...). Misdirected optimizations, I've heard some say.
至于可变性,许多早期的 JDK 类都受到它的影响(Point, Rectangle, Dimension, ...)。误导优化,我听到有人说。
The idea is that you want to be able to reuse objects (o.getPosition().x += 5) rather than creating copies (o.setPosition(o.getPosition().add(5, 0))) as you have to do with immutables. This may even have been a good idea with the early VMs, while it's most likely isn't with modern VMs.
这个想法是您希望能够重用对象 ( o.getPosition().x += 5) 而不是创建副本 ( o.setPosition(o.getPosition().add(5, 0))),因为您必须使用不可变对象。这对于早期的虚拟机来说甚至可能是一个好主意,而对于现代虚拟机来说很可能不是。
回答by cletus
Java's early APIs are nothing more than a product of their time. Immutability only became a popular concept years after that. You say that immutability is "obvious". That might be true now but it wasn't then. Just like dependency injection is now "obvious" but it wasn't 10 years ago.
Java 的早期 API 只不过是他们那个时代的产物。几年之后,不变性才成为一个流行的概念。你说不变性是“显而易见的”。现在可能是这样,但当时不是。就像依赖注入现在“显而易见”但不是 10 年前。
It was also at one time expensive to create Calendar objects.
曾经创建 Calendar 对象的成本也很高。
They remain that way for backwards compatibility reasons. What is perhaps more unfortunate was that once the mistake was realized the old class wasn't deprecated and new date/time classes were created for all APIs going forward. This has to some degree occurred with the JDK 8 adoption of a JodaTime like API (java.time, JSR 310) but really it's too little too late.
出于向后兼容性的原因,它们保持这种方式。可能更不幸的是,一旦意识到错误,旧类并没有被弃用,而是为未来的所有 API 创建了新的日期/时间类。这在一定程度上发生在 JDK 8 采用 JodaTime 之类的 API(java.timeJSR 310)时,但实际上为时已晚。
回答by dz.
Time is itself not easy to measure and to handle with. Just look at the length of the wikipedia article about time. And then, there are different understandings about time itself: a absoulte time point (as a constant), a time point at a certain place, a time range, the resolution of time....
时间本身并不容易衡量和处理。看看维基百科关于时间的文章的长度。然后,对时间本身也有不同的理解:一个绝对的时间点(作为一个常数),某个地点的一个时间点,一个时间范围,时间的分辨率……
I remember, when i saw java.util.Date the first time (JDK 1.0?) i was reallyhappy about it. The languages i knew of didn't had such a feature. I didn't have think about time conversion etc.
我记得,当我第一次看到 java.util.Date(JDK 1.0?)时,我真的很高兴。我知道的语言没有这样的功能。我没有考虑时间转换等。
I think it's mess, because everything that changes leaves a mess if you evolve from one level of understanding (XMLGregorianCaldender vs. Date) and requirements (Nanoseconds, past 2030) to higher level, but keeping the old untouched. And java.util.Date is not a Exception. Just look at the I/O subsystem or the transition from AWT to Swing...
我认为这是一团糟,因为如果您从一个理解级别(XMLGregorianCaldender 与日期)和需求(纳秒,2030 年以后)发展到更高级别,但保持旧的不变,那么所有变化都会留下一团糟。并且 java.util.Date 不是异常。只需看看 I/O 子系统或从 AWT 到 Swing 的过渡...
And because of that, "we should sometimes press the reset button." (who said that, btw.?)
正因为如此,“我们有时应该按下重置按钮。” (谁说的,顺便说一句。?)
回答by Jeshurun
You might find the following post interesting. It pretty much explains how the Calendar class got into the Java API in the first place, and sheds some light on the origins of the date class.
您可能会发现以下帖子很有趣。它首先解释了 Calendar 类是如何进入 Java API 的,并阐明了 date 类的起源。

