我可以交叉编译可选择使用 Java 8 中的类但编译为 Java 6 的 Java 代码吗?

Posted

技术标签:

【中文标题】我可以交叉编译可选择使用 Java 8 中的类但编译为 Java 6 的 Java 代码吗?【英文标题】:Can I cross compile Java code that optionally uses classes from Java 8 but is compiled to Java 6? 【发布时间】:2017-04-13 10:30:06 【问题描述】:

我知道交叉编译的 Java 代码不能使用新的语言功能,IE 没有 Java 8 中的 lambda 或 Java 7 中的 try-with-resources 等功能。 但是是否可以引用新 Java 版本中添加的新类?

假设我有一个支持 Java 6+ 的库,并且我有一些接受日期作为参数的方法。 对于 Java 6,我提供了一个使用 java.util.Date 的 API,但对于 Java 8 的用户,我想提供使用 java.time.Instant 的选项。

我希望 Java 6 用户能够使用该库,但如果他们尝试使用 Instant 方法会遇到 ClassNotFoundException

是否有一种可接受的方式来做这样的事情,以及如何使用 Gradle 或 Maven 等常用构建工具来实现?

给出的例子是人为的,请不要给出处理时间的替代方法的答案。

【问题讨论】:

通常,如果您的库与 Java 6 一起使用,则使用 Java 6 JDK 来创建和编译库。我知道您的示例是人为的,但 java.util.Date 仍然存在于 Java 8 中。您是正确的,如果您在 Java 6 JRE 上运行 Java 8 类文件,则可能会出现 ClassNotFoundException。 【参考方案1】:

不可能做到干净利落。提及 Java 8 类型的 API 不能在 Java 6 JRE 上加载。

如果您的 API 使用 Java 8 类,则 Java 6 客户端无法针对它进行编译。理论上,您可以用(比如)java.lang.Object 替换 Java 8 类,并要求客户端代码转换为 java.util.Datejava.time.Instant,具体取决于 执行 平台。但我不认为这是可以接受的,更不用说对试图使用你的库的程序员有用了。

无论如何,您都需要更改您的 API。


如果您确实需要支持 Java 6 并且还想在 API 中开始使用 Java 8 功能,我建议您支持两个单独的 API:

一个用于仅使用 Java 6 的 Java 6,以及 另一个也使用 Java 8 类型。

也许可以共享两个 API 版本背后的一些代码,但这取决于 Java 8 依赖项的“深度”程度。

但是,更好的办法是硬着头皮停止支持 Java 6 兼容性。 Java 6 已于 2013 年 2 月终止。 IMO,您有理由冻结您的 Java 6 API,然后将您的 Java 8 API 视为需要您的客户端的新版本切换到 Java 8。

【讨论】:

【参考方案2】:

我认为,如果您使用 Java 8 中的 javac(或 Gradle 或 Maven)进行编译,目标版本为 Java 6,但不设置 Java 6 中的类路径,它应该可以工作。但是您可能需要在类级别而不是方法级别进行拆分。

【讨论】:

【参考方案3】:

向后移植

正如其他答案所解释的,基本上答案是“否”。一种解决方法是将具有back-ports 功能的代码用于早期版本的 Java。

具体关于 java.time 类:

ThreeTen-BackportThreeTen-Backport 项目中的大部分 java.time 功能都向后移植到 Java 6 和 7。 ThreeTenABP上面的反向移植在ThreeTenABP 项目中进一步适配android

【讨论】:

以上是关于我可以交叉编译可选择使用 Java 8 中的类但编译为 Java 6 的 Java 代码吗?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 错误:在两个地方实现的类但我不接触的文件?

eclipse中的交叉编译器前缀和路径

QtCreator配置交叉编译工具链

Java 9 中的 Maven 更新,Eclipse 中的 Java 8 中的 Maven 编译

寻找类似 C++ STL 的向量类但使用堆栈存储

如何将 Java 源代码交叉编译为 JavaScript?