尽管使用 Java 8 个功能,项目如何支持 Java 7 个

How can a project support Java 7 despite using Java 8 features

我正在审查 github 上的 HikariCP 项目,它在其源代码中声明支持 "Java 7 and Java 8 maven artifact",它使用了一些 Java 8 个功能:

java.util.function.Consumer;
java.util.function.Predicate;
java.util.function.UnaryOperator;

我猜如果这个项目被其他人引用Java7,就会出错。那么,该项目是如何同时支持 Java 7 和 Java 8 的呢?

<plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>3.5.1</version>
               <extensions>true</extensions>
               <configuration>
                  <source>1.7</source>
                  <target>1.7</target>
               </configuration>
</plugin>

可能是项目的错误

指定源和目标级别仅尊重语言特性并影响字节码版本。未检查 API。

如果他们使用 JDK 8 构建项目,则项目构建良好。但我怀疑它会用 JDK 7.

编译

他们可能认为在这里指定 1.7 将使其支持 Java SE 7,这不会自动正确。

您是否尝试过使用 Java SE 7 访问图书馆?

该项目的好消息是,似乎很容易支持 Java SE 7。 FastList 只是一个 List 实现。由于 List 接口已在 Java SE 8 中得到扩展,因此即使它们仅抛出 UnsupportedOperationException,它们也被迫实现新方法。

通过使用 JDK 7 构建项目,他们可以轻松删除那些看似不需要的方法。

这不是一个错误(正如我自己所想的)。该项目确实使用了 Java 8 中的 classes。它不使用 Java 7 进行编译,并且其 Maven 构建也不使用 运行 和 Java 7 .

但是,由于 Java 8 特定功能(如 Lambda)在源代码中没有任何地方使用,因此 运行 和 Java 7.

尝试创建一个 Java 7 项目,将 HikariCP 声明为依赖项,然后 运行 执行以下代码:

import com.zaxxer.hikari.util.FastList;

public class Main {

    public static void main(String[] args) {

        FastList<String> fastList = new FastList<>(String.class);
        fastList.add("Hello");
        System.out.println(fastList);
    }
}

它 运行 成功了。另一方面,以下代码失败:

fastList.removeIf(null);

这是因为 removeIf() 和其他一些方法使用 Java 8 中的 classes,因此不能 运行 和 Java 7。但是他们都扔UnsupportedOperationException反正!您可能会注意到,唯一要导入 Java 8 classes 的 class 是 com.zaxxer.hikari.util.FastList。我不确定他们为什么这样做。

UPDATE:只是想澄清项目字节码的版本是 1.7,可以使用反编译器或 hexdump 轻松验证。它的源代码确实符合 Java 7,因此可以用

构建
<source>1.7</source>
<target>1.7</target>

正如@Puce 指出的那样。

另一方面,必须用JDK 1.8编译,这样源代码中引用的Java 8 class在编译时是可用的。一旦代码被编译,它可以 运行 和 Java 7 只要不尝试加载丢失的 Java 8 class(来自 java.util.function包在这种情况下)。