Java新时间API编译并在运行时中断

Java新时间API编译并在运行时中断,java,datetime,jsr310,Java,Datetime,Jsr310,我试图始终如一地使用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.Loc

我试图始终如一地使用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让我编写并编译它而不发出尖叫声?

它编译得很好,因为它接受a,并且是来自
TemporalAccessor
的子类

运行时会出现异常,因为要创建
Instant
TemporalAccessor
必须具有字段和,但是
LocalDateTime
不提供
Instant\u SECONDS
仅提供
NANO\u OF SECONDS

要从LocalDateTime创建即时,请更好地使用(例如):


在我个人的解释中(我可能遗漏了一些东西),JSR-310试图在代码编写和读取的便利性与静态和动态检查之间取得平衡。有一些非常通用的接口,允许您将多种对象传递给多种方法,但是如果您正在做一些毫无意义的事情(在设计人员看来),它将在运行时失败
TemporalAccessor
Instant.of()
的参数类型是这些接口之一,是的,
LocalDateTime
被声明为实现它,这就是代码编译的原因。
TemporalAccessor
支持许多字段。您可以通过其
isSupported()
方法查询其支持的字段
Instant.from()
被记录为需要字段
Instant\u SECONDS
NANO\u OF\u SECOND
,因此,如果您希望在尝试转换之前检查这些,而不是获取和处理异常。如果一个接口
TemporalAccessor
被支持字段的每个可思考的组合的接口替换,则可以获得编译时检查。想想看,新的
java.time
-API在编译时并没有被设计成类型安全的。尤其是来自(…)-的所有静态
方法都是不安全的,并且可能引发运行时异常。据我所知,新API的主要作者不喜欢泛型,因为泛型是提高编译时类型安全性的好方法@奥列夫。为来自(…)
-方法的
设计合理的签名并不是那么混乱。确实可行。只有一些比
TemporalAccessor
更具体的接口作为方法参数就足够了。我们最终都成功地正确使用了时间API,但在10名学生(已长大成人的开发人员,已经在编写旧java代码)的课程中,6遇到了这样的运行时异常。我们现在知道如何使用这个API,但我不会在一天结束时称它为强类型API。当然,我知道我可以做额外的检查,以确保它实际上可以同时使用新时间包中的不同对象。问题是:类的层次结构和类型不是为了防止这种语言的使用。对我来说,这就像用一个映射来编码一个对象:很明显,我所有的对象都是兼容的,但我必须做大量的检查,以确保它们确实在一起工作,并且在运行时不会崩溃?我认为这绝对不是“Javaïst”方法?我想
Instant.from(TemporalAccessor)
不太适合与其他
Java.time
类一起使用,有更好的方法来转换它们。它更倾向于尝试使新的时间api动态化,这样您就可以创建自己的时间对象并将其转换为所有其他对象,而无需创建任何转换方法。
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));