漫谈 IDEA 设置 JDK 版本

Posted 石头StoneWang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了漫谈 IDEA 设置 JDK 版本相关的知识,希望对你有一定的参考价值。

漫谈 IDEA 设置 JDK 版本

背景

IDEA里是相当多的地方可以设置JDK版本,很多资深的开发都未必知道其中区别,以及设置后产生的影响。当然本人也没有完全搞清楚,所以也需要众人拾柴。

如果出现版本的问题,比如编译错误,运行时提示版本错误,一般来说,版本都保持一致,就不会有问题。

仔细阅读本文,你会有不少收获的

IDEA里可设置JDK/JRE版本的地方

大略看看即可,这个子标题只列出可以设置jdk版本的地方,关于它的作用,在后续的标题下进行分析。

1、项目结构-Project

File->Project Structure...->Project图1

在这里插入图片描述

2、项目结构-Modules

File->Project Structure...->Modules -> Sources | Dependencies图2

在这里插入图片描述

在这里插入图片描述

3、新项目结构-Project

File -> New Projects Settings -> Structure for New Projects...图3

在这里插入图片描述

4、Java Compiler里

File -> Settings -> Build,Execution,Deployment -> Compiler -> Java Compiler图4

在这里插入图片描述

(有时候Module列表是是空的,一般是非Maven项目是空的,当然加是可以加上,只是没必要加)

5、Run Configuration里

Edit Configurations... (图5)

这个一般是main方法运行过后就会出现,也可以自行添加。有个JRE的版本的设置

在这里插入图片描述

说明

对上述可以设置JDK/JRE版本的各个地方做一个解读。

下面说的Project指的是项目工程,“项目”、“工程”、“项目工程”、“Project” 都是指通过File->new->Project… 建的东西;

“模块”、“Module”,都是指Project下的一个模块,在某个Project下也是可以File->new->Module的。

当然一般一个Project对应一个Module,也可以在一个Project下建多个Module

1、项目结构-Project (图1)
  • 仅本Project有效,其他不受影响

  • 修改的是本Project默认值,现有的Module不受影响(说明1),新建的Module用新值

    说明1:现有 Module 如果设置 Language level 为 Project default,或者 Module SDK 设为Project SDK,则会跟随 Project 配置的变动而变动

  • Project SDK 和 Project language level 有什么区别?见后面

2、项目结构-Modules (图2)
  • 修改仅影响本Module,其他不受影响

  • Language level (Sources)

    配置 IDEA用什么版本校验语法

    如果是非Maven项目,也是编译java文件的版本; maven项目不决定于这里,而决定于Java Compiler配置里的

  • Module SDK (Dependencies)

    是说项目引入的JDK依赖库。Module SDK 的改变,会导致 External Libraries 的改变。

    在这里插入图片描述

  • 如果设置为 Project default 和 Project SDK,Module的值会跟随Project的改变而改变

    在这里插入图片描述

    如果不想Module跟随,改成其他固定值

  • Language level,会受到maven.compiler.source 的影响 (maven项目才有) 详见后续 "关于maven的配置"

3、新项目结构-Project (图3)

新建项目的使用使用的(继承的)设置。只有Project设置,没有Module设置。

  • 显而易见,这是IDEA新建一个项目的时候采用的配置
  • 跟Project Structure的区别是:这里的配置是全局的,针对所有的新建的项目
  • 改变这里不影响已有的项目
4、Java Compiler里 (图4)
  • 作用是指定class文件要用什么版本编译成的class

  • 非Maven的Project没有module,非Maven的项目,用什么版本编译java文件,决定于Language level的配置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bwUqloxv-1623407192147)(C:\\Users\\xuanxiao\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210611160542273.png)]

  • 对于Maven项目,会受到 maven.compiler.target 的影响。详见后续 "关于maven的配置"
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>
5、Run Configuration里 (图5)

是说运行程序用的是什么版本的 JRE

  • 如果是用1.8编译的,JRE选1.7肯定是无法运行的,可以选择>=1.8的,比如用1.9是可以的
  • 默认的值是 Default,即跟随Module SDK (即 Modules->Dependencies->Module SDK)

在这里插入图片描述

补充

1、究竟Language Level是干嘛的
  • 在非Maven项目里,这是管编译java文件用什么版本的
  • 在Maven项目里,是配置给IDEA看的,让IDEA用指定版本的语法检查你的源码。

例如 JDK5 引入了泛型,可以这么写:

List<String> list = new ArrayList<String>();

但是不能这么写:

List<String> list = new ArrayList<>();

这个写法要到JDK7之后才可以,所以如果Language level 小于7(比如5或6),IDEA会提示你语法错误,但是改成>=7的版本就不提示错误了。所以这个配置就是告诉 IDEA用什么版本的语法检查源码,以便提示编译错误。

2、关于maven的配置
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>
  • maven.compiler.source 的值决定了 Language level 的配置

    如果将 Language level 修改成不一致,在 reimport(刷新) Maven配置后会恢复成 maven.compiler.source 的值

  • maven.compiler.target 的值决定了 Java Compiler里的target bytecode version

    跟上面一样,如果两者指定的版本不一致,在刷新Maven后会恢复

  • 如果Maven项目没有上述配置,则默认都是1.5

    会发生 “即使你改了 Language level 和 Java Compiler 里的 target bytecode version”,刷新后恢复成1.5

    详细参考这里

    最佳实践:maven项目最好有这个配置

reimport 是指这里

在这里插入图片描述

3、关于 System.getProperty("java.version"); 是什么版本?

是JRE的版本,不是class的编译版本。

比如你的源码是jdk8编译的,如果在Run Configuration里修改为jdk9的版本,获得的值是9的版本,说明这里获得的值是JRE。

4、如何知道class是用什么版本编译的

有多种方法

  1. 双击打开class文件,会显示(最方便)

    在这里插入图片描述

  2. 用jclasslib

    在这里插入图片描述

  3. 用javap命令

    javap命令,无论用 javap -v -p Xxx.class 还是 javap -v 能看到 major version 就行

5、关于Java Compiler里有时候会空的

非Maven项目默认是没有Module的 (maven项目默认会有)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X1B3I498-1623407192155)(C:\\Users\\xuanxiao\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210611160542273.png)]

当然是可以点击+号添加的。不添加,则编译的版本跟Language level保持一致。很明显,你手动添加后也可以看到,也提示你 Same as language level

在这里插入图片描述

这里确实是可以改成和language level的版本不同(不过谁吃饱撑着改成版本不一),但是会导致Information:java:javacTask:源发型版本xxxxx 的错误。

6、我如何添加sdk版本?

在这里插入图片描述

先安装,自己选择需要的版本即可,不需要都装。另外很多的jdk安装的时候会提示安装jre(少数不会,好像jdk5就不会),不需要安装,我留了一个jre8。

在 IDEA 里进行添加,

在File->New Projects Settings->Structure for New Projects…->Platform Settings->SDKs里进行添加,是全局的

或者在File->Project Structure…->Platform Settings->SDKs里进行添加,也是全局的

常见的关于JDK版本的报错

1、Diamond types are not supported at language level ‘5’

修改language level即可能可以临时解决

diamond指钻石,即钻石符号(<>),长得像钻石吧!

所以看到diamond这个单词,就要想起这个符号,sql里也用这个表示 “不等于”。jdk5里虽然有泛型的写法,但是这种写法List<String> list = new ArrayList<>();只有jdk7之后才能用钻石符号,否则就怪怪不省略,使用 List<String> list = new ArrayList<String>();

在这里插入图片描述

为什么说可能是临时的解决方案?

因为对于非maven的项目,你在Project Structure里Modules里改了Language level就是改了,但是对于maven项目,你改了有可能会打回原型,必须配置

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

PS: 下面是细节,以前我以为 Diamonds 是指泛型,犯过错,曾经也稀里糊涂
在这里插入图片描述

2、java.lang.UnsupportedClassVersionError: com/wyf/test/non/T : Unsupported major.minor version 52.0

举个例子,如果你的class是jdk8编译的,如果你切换成7运行。

这里的 52.0 是不支持的版本,指你的class文件是用52版本编译的,不支持。

为什么会不支持?

你用52版本编译的,肯定不能用低于52的JRE运行。这里你肯定用了<52版本的JRE在运行它。

52指 jdk8,51指 jdk7,53是 jdk9,如此类推。

解决方法:提高Module SDK的版本,由于Run Configuration里JRE的设置一般是跟随Module SDK的

3、Information:java: javacTask: 源发行版 8 需要目标发行版 1.8

在这里插入图片描述

这个乍看错误提示似乎不太好定位问题所在,不过肯定是配置的问题。那怎么解决呢?你把本文提到的那些配置的地方,检查一下,改成一致版本。

以上是关于漫谈 IDEA 设置 JDK 版本的主要内容,如果未能解决你的问题,请参考以下文章

idea设置JDK无效

IDEA-Maven项目的jdk版本设置

idea 构建java项目时设置jdk版本来编译

Idea15 常用设置:JDKSVN

idea中调用jdk的方法时怎么自动补充里面的参数

idea 模块jdk依赖总是自动变为jdk1.5