【问题标题】:Java new time API compiles and break at run timeJava new time API 在运行时编译和中断
【发布时间】:2018-05-22 11:33:50
【问题描述】:

我正在尝试始终如一地使用 Java 8 日期时间 API,我正在寻找这种行为背后的解释:

Instant.from(LocalDateTime.of(2017,01,01,0,0,0,0))

编译得很好,但会产生:

Exception in thread "main" java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: 2017-01-01T00:00 of type java.time.LocalDateTime

我的问题是:如果这些类型不兼容,为什么 API 让我编写代码并编译它而不用尖叫?

【问题讨论】:

  • 在我个人的解释中(我可能遗漏了一些东西)JSR-310 试图在代码编写和阅读的便利性与静态和动态检查之间取得平衡。有一些非常通用的接口允许您将多种对象传递给多种方法,但是如果您正在做一些无意义的事情(在设计者看来),它将在运行时失败。 TemporalAccessorInstant.of() 的参数类型,是这些接口之一,是的,LocalDateTime 被声明为实现它,这就是你的代码编译的原因。
  • TemporalAccessor 支持多个字段。您可以通过其isSupported() 方法查询其支持的字段。 Instant.from() 被记录为需要字段 INSTANT_SECONDSNANO_OF_SECOND,因此如果您更喜欢这种方式而不是获取和处理异常,则可以在尝试转换之前检查这些字段。
  • 您可以获得编译时检查,如果一个接口TemporalAccessor 将被支持字段的每个可想到组合的接口替换。想想那会是多么的一团糟
  • 新的java.time-API 并未设计为在编译时是类型安全的。尤其是所有静态from(...)-方法都是不安全的,并且可能引发运行时异常。据我所知,新 API 的主要作者不喜欢泛型,因为泛型本来是提高编译时类型安全性的好方法。 @OleV.V.为from(...)-methods 设计合理的签名并不是那么一团糟。确实可行。只有一些比TemporalAccessor 更具体的接口作为方法参数就足够了。
  • 最终我们都成功地正确使用了时间 API,但在 10 名学生(成年开发人员,已经编写过较旧的 Java)课程中,有 6 名遇到了此类运行时异常。我们现在知道如何使用这个 API,但我最终不会称它为强类型 API。

标签: java datetime jsr310


【解决方案1】:

它编译得很好,因为Instant.from(TemporalAccessor temporal) 接受TemporalAccessor 并且LocalDateTimeTemporalAccessor 的子类。

在运行时会出现异常,因为要创建InstantTemporalAccessor 必须具有字段INSTANT_SECONDSNANO_OF_SECOND,但LocalDateTime 不提供INSTANT_SECONDSNANO_OF_SECOND

更好地使用(例如)从 LocalDateTime 创建 Instant:

LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zoneId = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zoneId).toInstant();

LocalDateTime localDateTime = LocalDateTime.now();
Instant instant = localDateTime.toInstant(ZoneOffset.ofHours(0));

【讨论】:

  • 当然,我知道我可以进行额外的检查,以确保实际上可以同时使用新时间包中的不同对象。问题是:类层次结构和类型不是为了防止这种语言的使用。对我来说,这就像使用地图对对象进行编码:显然我的所有对象都是兼容的,但我必须进行大量检查以确保它们真正一起工作并且不会在运行时爆炸?我虽然这绝对不是“Javaïst”方式?
  • 我猜Instant.from(TemporalAccessor) 不太打算与其他java.time 类一起使用,有更好的方法来转换它们。它更多的是尝试使新的时间 api 动态化,因此您可以创建自己的时间对象并将其转换为所有其他时间对象,而无需创建任何转换方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-08
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多