为什么 Date 构造函数已被弃用,我应该使用什么来代替?
我来自 C# 世界,所以对 Java 还不太有经验。 Eclipse 刚刚告诉我 Date
已被弃用:
Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));
为什么?应该使用什么(特别是在上述情况下)来代替?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
目前大多数 Java 开发人员使用第三方包 Joda-Time。它被广泛认为是一个更好的实现。
然而,Java 8 将有一个新的 java.time.* 包。请参阅这篇文章介绍 JDK 8 的新日期和时间 API 。
Most Java developers currently use the third party package Joda-Time. It is widely regarded to be a much better implementation.
Java 8 however will have a new java.time.* package. See this article, Introducing the New Date and Time API for JDK 8.
Date 构造函数期望年份格式为自 1900 年以来的年份、从零开始的月份、从一开始的日期,并将小时/分钟/秒/毫秒设置为零。
因此,使用 Calendar 替换(从零开始的年份、从零开始的月份、从一开始的日期)来替换已弃用的 Date 构造函数,我们需要类似以下内容:
或者使用 Java 1.8(它具有从零开始的年份和从一开始的月份以及days):
以下是 Date、Calendar 和 Java 1.8 的相同版本:
The Date constructor expects years in the format of years since 1900, zero-based months, one-based days, and sets hours/minutes/seconds/milliseconds to zero.
So using the Calendar replacement (zero-based years, zero-based months, one-based days) for the deprecated Date constructor, we need something like:
Or using Java 1.8 (which has zero-based year, and one-based months and days):
Here are equal versions of Date, Calendar, and Java 1.8:
与 binnyb 建议的类似,您可以考虑使用较新的 Calendar >公历日历方法。请参阅这些最新文档:
http://download.oracle .com/javase/6/docs/api/java/util/GregorianCalendar.html
Similar to what binnyb suggested, you might consider using the newer Calendar > GregorianCalendar method. See these more recent docs:
http://download.oracle.com/javase/6/docs/api/java/util/GregorianCalendar.html
您可以使用
Calendar
类在代码中创建类似于new Date(year,month,date)
的方法。它将像已弃用的
Date
构造函数一样工作You can make a method just like
new Date(year,month,date)
in your code by usingCalendar
class.It will work just like the deprecated constructor of
Date
我从 Java 安全代码指南 得到这个
I got this from Secure Code Guideline for Java
(Java-8 之前的方式)
(the pre-Java-8 way)
java.util.Date 类实际上并未被弃用,只是该构造函数以及其他几个构造函数/方法被弃用。它已被弃用,因为这种用法不能很好地适应国际化。应使用
Calendar
类:查看日期 Javadoc:
http://download.oracle.com/javase/6/docs/api/java/util/Date.html
The
java.util.Date
class isn't actually deprecated, just that constructor, along with a couple other constructors/methods are deprecated. It was deprecated because that sort of usage doesn't work well with internationalization. TheCalendar
class should be used instead:Take a look at the date Javadoc:
http://download.oracle.com/javase/6/docs/api/java/util/Date.html
tl;dr
…or…
详细信息
java.util.Date
、java.util.Calendar
和java.text.SimpleDateFormat
类被匆忙处理当 Java 首次推出和发展时,速度太快了。这些课程设计或实施得不好。尝试了改进,因此您发现了弃用。不幸的是,改进的尝试基本上失败了。您应该完全避免这些课程。它们在 Java 8 中被新类取代。代码中的问题
java.util.Date 同时具有日期和时间部分。您忽略了代码中的时间部分。因此,Date 类将采用 JVM 默认时区定义的一天的开始时间,并将该时间应用于 Date 对象。因此,代码的结果将根据运行的机器或设置的时区而有所不同。可能不是你想要的。
如果您只需要日期,而不需要时间部分(例如出生日期),您可能不想使用
Date
对象。您可能只想存储日期字符串,采用 ISO 8601 格式YYYY -MM-DD
。或者使用LocalDate
来自 Joda-Time 的对象(见下文)。Joda-Time
在 Java 中学习的第一件事:避免众所周知的麻烦的 java.util.Date & 。 java.util.Calendar 类与 Java 捆绑在一起。
正如 user3277382 的答案中正确指出的,使用 Joda-Time 或新的 Java 8 中的 java.time.* 包。
示例Joda-Time 2.3 中的代码
转储到控制台...
运行时...
java.time
在本例中,代码为 java.time 与 Joda-Time 几乎相同一个>。
我们得到一个时区(
ZoneId
),并构造一个分配给该时区的日期时间对象(ZonedDateTime
)。然后使用 不可变对象 模式,我们根据旧对象的同一时刻创建新的日期时间(自 epoch 以来的纳秒计数,但分配了其他时间区。最后我们得到一个LocalDate
< /a> 没有时间或时区,但请注意在确定日期时适用时区(新的一天在 奥斯陆比纽约)。关于 java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如
java.util.Date
< /a>,日历
,&SimpleDateFormat< /代码>
。
要了解更多信息,请参阅 Oracle 教程 。并在 Stack Overflow 上搜索许多示例和解释。规范为 JSR 310。
Joda-Time 项目,现已在 维护模式,建议迁移到java.time 类。
您可以直接与数据库交换java.time对象。使用符合 JDBC 驱动程序 jeps/170" rel="noreferrer">JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类。 Hibernate 5 和 Hibernate 5 JPA 2.2 支持 java.time。
从哪里获取 java.time 类?
tl;dr
…or…
Details
The
java.util.Date
,java.util.Calendar
, andjava.text.SimpleDateFormat
classes were rushed too quickly when Java first launched and evolved. The classes were not well designed or implemented. Improvements were attempted, thus the deprecations you’ve found. Unfortunately the attempts at improvement largely failed. You should avoid these classes altogether. They are supplanted in Java 8 by new classes.Problems In Your Code
A java.util.Date has both a date and a time portion. You ignored the time portion in your code. So the Date class will take the beginning of the day as defined by your JVM’s default time zone and apply that time to the Date object. So the results of your code will vary depending on which machine it runs or which time zone is set. Probably not what you want.
If you want just the date, without the time portion, such as for a birth date, you may not want to use a
Date
object. You may want to store just a string of the date, in ISO 8601 format ofYYYY-MM-DD
. Or use aLocalDate
object from Joda-Time (see below).Joda-Time
First thing to learn in Java: Avoid the notoriously troublesome java.util.Date & java.util.Calendar classes bundled with Java.
As correctly noted in the answer by user3277382, use either Joda-Time or the new java.time.* package in Java 8.
Example Code in Joda-Time 2.3
Dump to console…
When run…
java.time
In this case the code for java.time is nearly identical to that of Joda-Time.
We get a time zone (
ZoneId
), and construct a date-time object assigned to that time zone (ZonedDateTime
). Then using the Immutable Objects pattern, we create new date-times based on the old object’s same instant (count of nanoseconds since epoch) but assigned other time zone. Lastly we get aLocalDate
which has no time-of-day nor time zone though notice the time zone applies when determining that date (a new day dawns earlier in Oslo than in New York for example).About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
,Calendar
, &SimpleDateFormat
.To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for
java.sql.*
classes. Hibernate 5 & JPA 2.2 support java.time.Where to obtain the java.time classes?
特定的
Date
构造函数已弃用,应使用Calendar
代替。日期JavaDoc a> 描述了哪些构造函数已被弃用以及如何使用
日历
替换它们。The specific
Date
constructor is deprecated, andCalendar
should be used instead.The
JavaDoc
for Date describes which constructors are deprecated and how to replace them using aCalendar
.我发现这个问题是一个较新的问题的重复,它询问什么获取特定年、月、日的
Date
的未弃用方法是。到目前为止,这里的答案是使用
Calendar
类,在 Java 8 出现之前都是如此。但从 Java 8 开始,执行此操作的标准方法是:然后,如果您确实需要
java.util.Date
,则可以使用 这个问题。有关详细信息,请查看API 或Java 8 教程。
I came across this question as a duplicate of a newer question which asked what the non-deprecated way to get a
Date
at a specific year, month, and day was.The answers here so far say to use the
Calendar
class, and that was true until Java 8 came out. But as of Java 8, the standard way to do this is:And then if you really really need a
java.util.Date
, you can use the suggestions in this question.For more info, check out the API or the tutorials for Java 8.
不推荐使用构造函数的原因之一是年份参数的含义不是您所期望的。 javadoc 说:
请注意,年份字段是自
1900
以来的年数,因此您的示例代码很可能不会执行您期望的操作。这就是重点。一般来说,
Date
API 仅支持现代西历,具有特殊指定的组件,并且如果您设置字段,则行为会不一致。Calendar
和GregorianCalendar
API 比Date
更好,并且第 3 方 Joda-time API 通常被认为是最好的。在 Java 8 中,他们引入了 java.time 包,这些包现在是推荐的替代方案。One reason that the constructor is deprecated is that the meaning of the year parameter is not what you would expect. The javadoc says:
Notice that the year field is the number of years since
1900
, so your sample code most likely won't do what you expect it to do. And that's the point.In general, the
Date
API only supports the modern western calendar, has idiosyncratically specified components, and behaves inconsistently if you set fields.The
Calendar
andGregorianCalendar
APIs are better thanDate
, and the 3rd-party Joda-time APIs were generally thought to be the best. In Java 8, they introduced thejava.time
packages, and these are now the recommended alternative.请注意,
Calendar.getTime()
是不确定的,因为白天时间部分默认为当前时间。要重现,请尝试运行以下代码几次:
输出例如:
几分钟后运行完全相同的代码会产生:
因此,虽然
set()
强制相应的字段使用正确的值,但它会泄漏其他字段的系统时间。 (上面使用Sun jdk6 & jdk7测试)Please note that
Calendar.getTime()
is nondeterministic in the sense that the day time part defaults to the current time.To reproduce, try running following code a couple of times:
Output eg.:
Running the exact same code a couple of minutes later yields:
So, while
set()
forces corresponding fields to correct values, it leaks system time for the other fields. (Tested above with Sun jdk6 & jdk7)Date
本身并未被弃用。只是它的方法很多而已。 请参阅此处了解详细信息。使用
java.util.Calendar
相反。Date
itself is not deprecated. It's just a lot of its methods are. See here for details.Use
java.util.Calendar
instead.由于 Date 构造函数已被弃用,您可以尝试此代码。
As the Date constructor is deprecated, you can try this code.