在Java开发中许多童鞋经常被各种版本的JDK搞得晕头转向本节我们就来详细讲解Java程序编译后的class文件版本问题。我们通常说的Java 8Java 11Java 17是指JDK的版本也就是JVM的版本更确切地说就是java.exe这个程序的版本$ java -version java version 17 2021-09-14 LTS而每个版本的JVM它能执行的class文件版本也不同。例如Java 11对应的class文件版本是55而Java 17对应的class文件版本是61。如果用Java 11编译一个Java程序输出的class文件版本默认就是55这个class既可以在Java 11上运行也可以在Java 17上运行因为Java 17支持的class文件版本是61表示“最多支持到版本61”。如果用Java 17编译一个Java程序输出的class文件版本默认就是61它可以在Java 17、Java 18上运行但不可能在Java 11上运行因为Java 11支持的class版本最多到55。如果使用低于Java 17的JVM运行会得到一个UnsupportedClassVersionError错误信息类似java.lang.UnsupportedClassVersionError: Xxx has been compiled by a more recent version of the Java Runtime...只要看到UnsupportedClassVersionError就表示当前要加载的class文件版本超过了JVM的能力必须使用更高版本的JVM才能运行。打个比方用Word 2013保存一个Word文件这个文件也可以在Word 2016上打开。但反过来用Word 2016保存一个Word文件就无法使用Word 2013打开。但是且慢用Word 2016也可以保存一个格式为Word 2013的文件这样保存的Word文件就可以用低版本的Word 2013打开但前提是保存时必须明确指定文件格式兼容Word 2013。类似的对应到JVM的class文件我们也可以用Java 17编译一个Java程序指定输出的class版本要兼容Java 11即class版本55这样编译生成的class文件就可以在Java 11的环境中运行。指定编译输出有两种方式一种是在javac命令行中用参数--release设置$ javac --release 11 Main.java参数--release 11表示源码兼容Java 11编译的class输出版本为Java 11兼容即class版本55。第二种方式是用参数--source指定源码版本用参数--target指定输出class版本$ javac --source 9 --target 11 Main.java上述命令如果使用Java 17的JDK编译它会把源码视为Java 9兼容版本并输出class为Java 11兼容版本。注意--release参数和--source --target参数只能二选一不能同时设置。然而指定版本如果低于当前的JDK版本会有一些潜在的问题。例如我们用Java 17编译Hello.java参数设置--source 9和--target 11public class Hello { public static void hello(String name) { System.out.println(hello.indent(4)); } }用低于Java 11的JVM运行Hello会得到一个LinkageError因为无法加载Hello.class文件而用Java 11运行Hello会得到一个NoSuchMethodError因为String.indent()方法是从Java 12才添加进来的Java 11的String版本根本没有indent()方法。注意如果使用--release 11则会在编译时检查该方法是否在Java 11中存在。因此如果运行时的JVM版本是Java 11则编译时也最好使用Java 11而不是用高版本的JDK编译输出低版本的class。如果使用javac编译时不指定任何版本参数那么相当于使用--release 当前版本编译即源码版本和输出版本均为当前版本。在开发阶段多个版本的JDK可以同时安装当前使用的JDK版本可由JAVA_HOME环境变量切换。源码版本在编写源代码的时候我们通常会预设一个源码的版本。在编译的时候如果用--source或--release指定源码版本则使用指定的源码版本检查语法。例如使用了lambda表达式的源码版本至少要为8才能编译使用了var关键字的源码版本至少要为10才能编译使用switch表达式的源码版本至少要为12才能编译且12和13版本需要启用--enable-preview参数。喜欢这个系列的同学可以关注我爆肝一个月Python 从入门到精通