我可以交叉编译可选择使用 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.Date
或 java.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 代码吗?的主要内容,如果未能解决你的问题,请参考以下文章