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