【问题标题】:what's the difference between -source and -target compatibility?-source 和 -target 兼容性有什么区别?
【发布时间】:2012-05-26 16:00:03
【问题描述】:

当使用Java编译器(javac)时,我们可以指定两种兼容性。一个使用-source,另一个使用-target。这两者有什么区别?

例如,-source 1.5-target 1.6?

另外,是否存在我们使用不同的源和目标兼容级别的情况?

【问题讨论】:

    标签: java compilation javac backwards-compatibility


    【解决方案1】:

    来自javac docs

    -source 指定接受的源代码版本。

    -target 生成以指定 VM 版本为目标的类文件。类文件将在指定的目标和更高版本上运行,但不会在 VM 的早期版本上运行。

    在你的例子中:

    -source 1.5 and -target 1.6
    

    这将用于确保源代码与 JDK 1.5 兼容,但应生成用于 JDK 1.6 及更高版本的类文件。

    为什么你会这样做是另一回事。

    【讨论】:

    • 请注意,我发现javac 不支持所有组合。我实际上也有一个用例。在 Java 6 中,JAX-WS 是内置的,所以我希望有一个解决方案可以在纯 Java 6 上运行,而不需要额外的库。然后,该解决方案需要一些客户在 Java 5 JVM(以及附带的 JAX-WS)上可执行,并且 @Override 语法发生了更改,因此 Java 5 javac 无法立即编译它。 (这是前 maven,今天可能更容易做到)
    • 另请参阅-bootclasspath,如this answer 中所述。
    • @skaffman - “你为什么要这样做是另一回事......” - Java 试图解释 cmets。如果语言设置不正确,那么编译可能会因为 cmets 中的非法字符而失败!!!有时更容易告诉编译器停止解释 cmets,然后在数百个文件中修复版权声明。
    • @skaffman:+1 表示“类文件将在指定的目标和更高版本上运行,但不会在早期版本的 VM 上运行。”
    • 我希望你也能简要解释一下原因。
    【解决方案2】:

    -source 表示您的源代码的合规级别:您是否使用注释?那么你至少需要1.5;你在接口实现上使用@override,你需要1.6

    -target 指定您希望能够在哪个 Java 版本上运行您的类。您可以使用 Java SE 7 编译器并编译以在 Java SE 1.5 上运行。

    【讨论】:

      【解决方案3】:

      这对于生成使用旧版本 Java 的 jar 文件非常有用。 我相信到目前为止所有的 JDK 都能够执行旧版本,所以没有真正的理由让目标大于源。

      然而,将target 设置为例如使用 1.7 JDK 时为 1.6。

      我不确定,但我相信它可以在某些情况下使用 1.7 编译器将 1.7 java 代码编译为 1.6 jar,例如表达式

      ArrayList<Integer> foo = new ArrayList<>();
      

      仅在 1.7+ 源版本中有效的应编译为 1.6 兼容字节码。但我还没有验证编译器是否真的会这样做。 不幸的是,这似乎没有在实践中实现。

      【讨论】:

      • 虽然这是一个很好的理论,但实际上不会这样做。如果您尝试源 1.7 和目标 1.6,您将收到此错误:“源版本 1.7 需要目标版本 1.7”
      • 我发现@Tomas 说的是真的。哪个令人讨厌,因为这似乎是最有用的组合?它阻止您编写可以在 1.6 项目中链接的 1.7 源代码级别的库。有什么解决办法吗?
      • @Matthias 链接来自不同类文件版本的库没有问题。使用-target 1.6 的唯一原因是运行代码的JVM 是1.6。
      • 目标版本低于源版本意味着编译器必须能够为旧运行时编译新语言功能。虽然在某些情况下这是可能的,但肯定有一些情况并非如此。例如,您无法对 jar 文件执行任何操作来忠实地模仿 Project Valhalla 的值类型在 1.6 JVM 上的行为。因此目标版本 >= 源版本。 99% 的时间您都知道您的目标版本是什么,然后将源版本设置为相同,以便尽可能多地使用 Java。
      • 瓦尔哈拉是高度实验性的。无论如何,你不能指望它有太多的兼容性保证。但是,您可以期望 JDK10 能够生成与 JDK8 兼容的字节码。更大的问题通常是您可能无意中使用了一些在 JDK 8 中尚不存在的功能。比如使用 Path.of() 代替 Paths.get() 将 String 转换为 NIO Path。它将为 Java 8 VM 生成 bytecode,但仍需要更高版本的 JRE。因此,如果您有一个需要编译以在 Java 8 VM 上运行的 Java 8 源代码,这主要很有用,但您的编译器比 8 更新。
      猜你喜欢
      • 2011-05-26
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 2011-03-10
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多