1. 这个警告到底在说什么如果你用 IntelliJ IDEA 跑一个 Maven 项目编译输出里突然冒出一行黄字Warning:java: 源值 1.5 已过时, 将在未来所有发行版中删除 Warning:java: 目标值 1.5 已过时, 将在未来所有发行版中删除先别慌这不是你代码写错了也不是依赖冲突更不是 IDEA 抽风。它说的是编译器正在用 Java 5 的语言级别source和字节码版本target来编译你的代码而 Java 5 这个级别早就被标记为过时了未来的 JDK 版本会彻底移除对它的支持。这个警告的本质是Maven 编译插件maven-compiler-plugin没有拿到明确的 source/target 配置于是它退回到了一个非常古老的默认值。在比较老的 maven-compiler-plugin 版本里默认的 source 和 target 就是 1.5。你的 JDK 可能是 8、11、17 甚至 21但编译插件压根没理会它自顾自地按 1.5 的规则来。这件事的迷惑性在于你的项目可能跑起来完全正常。因为大多数业务代码不会用到 Java 5 之后才有的语法特性所以编译能过、测试能跑、打包能成。但隐患是实打实的——你写的 lambda、try-with-resources、var、switch 表达式、文本块只要用了新语法编译就会直接报错而不是警告。更隐蔽的是字节码版本停留在 1.5意味着你没法用上高版本 JVM 的很多优化和特性某些依赖库如果要求更高的字节码版本运行时可能抛出UnsupportedClassVersionError。所以这行警告的正确态度是必须处理而且处理起来很简单。它属于那种不处理也能跑但处理了才专业的典型问题。下面我把这个问题的来龙去脉、几种解决方案、以及每种方案背后的取舍完整地拆一遍。2. 为什么 Maven 会默认用 1.52.1 编译插件的默认值历史包袱要理解这个警告得先知道 Maven 的编译插件是怎么演进的。maven-compiler-plugin 在很早期的版本比如 2.x 系列里source和target的默认值就是1.5。这个默认值定下来的时候Java 5 还是主流谁也没想到后面会出这么多版本。后来 Java 6、7、8 陆续发布但编译插件的默认值一直没改原因很简单改默认值会破坏向后兼容。如果某个老项目一直依赖 1.5 的编译行为插件突然把默认值提到 8可能会导致一些边缘情况下的编译结果变化。Maven 社区选择了保守策略——默认值不动让用户在 pom 里显式声明。到了 maven-compiler-plugin 3.8.0 之后情况有所变化默认值开始跟随运行时的 JDK 版本走。但如果你用的是老版本插件或者项目继承的父 pom 里锁定了老版本那 1.5 的默认值就会一直生效。这就是为什么同样一个项目在同事机器上没警告在你机器上有警告——很可能是因为插件版本或者父 pom 配置不同。2.2 IDEA 和 Maven 的双重配置陷阱这里有个很多人踩过的坑IDEA 自己有一套编译配置Maven 也有一套编译配置两者是独立的。你在 IDEA 里打开File - Project Structure - Project看到Language level可能显示的是 8 或者 11于是你以为没问题。但实际上当你通过 Maven 的生命周期比如mvn compile来编译时用的是 pom 里 maven-compiler-plugin 的配置跟 IDEA 的 Project Structure 设置没关系。反过来也一样。如果你在 IDEA 里直接点运行按钮IDEA 可能用自己的一套配置来编译这时候 pom 里的配置又不一定生效。这种两套配置各管各的的机制是导致这个警告反复出现、改了这里那里又冒出来的根本原因。提示判断当前到底是谁在编译看输出日志的前几行。如果看到mvn相关的命令行输出就是 Maven 在编译如果是 IDEA 自己的 Build 输出就是 IDEA 在编译。两者要分别配置。2.3 父 pom 和依赖传递的隐形影响还有一种情况你的项目 pom 里明明没写 compiler 插件配置但警告还是出现了。这时候要往上查——你的项目可能继承了一个父 pom而父 pom 里配置了 1.5。Maven 的 pom 继承机制意味着父 pom 里的buildplugins配置会被子项目继承。如果父 pom 是公司内部的基础 pom或者某个开源项目的 parent里面锁定了老版本的编译插件和 1.5 的 source/target那你子项目不显式覆盖的话就会一直用 1.5。排查方法很简单在项目根目录执行mvn help:effective-pom这个命令会打印出合并了所有继承关系之后的最终生效 pom。在里面搜索maven-compiler-plugin看source和target到底是什么值。如果显示 1.5那就找到源头了。3. 四种解决方案的对比与选择解决这个警告核心就是告诉 maven-compiler-plugin 用哪个 Java 版本。但具体怎么告诉有四种常见做法各有适用场景。我先把它们列出来再逐个分析。方案配置位置优点缺点推荐场景方案一pom 的 properties简单、通用、改一处生效依赖插件版本支持绝大多数项目首选方案二pom 的 plugin 配置精确控制、可配额外参数配置略长需要精细控制的场景方案三IDEA 全局设置不改项目文件只对 IDEA 生效、团队不一致临时本地调试方案四升级插件版本一劳永逸可能引入其他变化老项目现代化改造3.1 方案一用 properties 声明版本最推荐这是最简洁、最通用的做法。在 pom 的properties节点里加两行properties maven.compiler.source8/maven.compiler.source maven.compiler.target8/maven.compiler.target /propertiesmaven-compiler-plugin 会自动读取这两个属性把它们作为 source 和 target 的值。这个机制从插件 3.0 版本开始就支持了所以兼容性很好。为什么推荐这个方案因为它不依赖具体的插件配置块即使父 pom 里配置了插件properties 里的值通常也能覆盖取决于父 pom 的配置方式。而且它足够直观任何人打开 pom 一眼就能看到项目用的 Java 版本。把8换成你实际使用的版本比如11、17、21。这里要注意source 和 target 最好保持一致不要一个 8 一个 11否则可能出现编译能过但运行报错的情况。3.2 方案二直接配置编译插件如果你需要更精细的控制比如同时指定编码、开启某些编译参数那就直接配置插件build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration source17/source target17/target encodingUTF-8/encoding /configuration /plugin /plugins /build这个方案的好处是所有编译相关的配置都集中在一处包括编码、source、target、是否显示警告等。缺点是配置块比较长而且如果父 pom 里也配了这个插件可能出现配置合并的复杂情况。这里我特意加了encodingUTF-8/encoding因为中文项目里编码问题也是高频坑。不指定编码的话Maven 会用平台默认编码在 Windows 上可能是 GBK导致中文注释乱码或者编译报错。3.3 方案三IDEA 设置里改只治标如果你只是想让 IDEA 里的警告消失不想动项目文件可以在 IDEA 设置里改File - Settings - Build, Execution, Deployment - Compiler - Java Compiler把Target bytecode version改成你想要的版本。或者在File - Project Structure - Project里改Language level。但这个方案有个致命问题它只对你本地的 IDEA 生效不改项目文件。也就是说同事拉下代码后警告照样出现CI 服务器上跑 Maven 构建警告也照样出现。所以这个方案只适合临时调试不适合作为团队项目的正式解决方案。3.4 方案四升级编译插件版本如果你的项目用的是很老的 maven-compiler-plugin比如 2.x 或 3.0 以下升级到新版本也能解决问题因为新版本的默认值会跟随 JDKplugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.13.0/version /plugin但升级插件版本要谨慎因为新版本可能对某些编译行为有调整。建议先在本地跑一遍完整构建和测试确认没问题再提交。4. 完整实操从排查到验证光看方案还不够我把完整的操作流程走一遍你可以直接照着做。4.1 第一步确认当前生效的配置在项目根目录执行mvn help:effective-pom | grep -A 10 maven-compiler-plugin如果输出里能看到source1.5/source或者压根没有 source 配置那就确认了问题所在。同时留意插件的version如果是 3.0 以下建议一并升级。4.2 第二步修改 pom打开项目根目录的 pom.xml在properties里加上版本声明。假设你的 JDK 是 17properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target /properties顺手把project.build.sourceEncoding也加上这是 Maven 官方推荐的做法能避免很多编码相关的诡异问题。4.3 第三步刷新 Maven 并重新编译在 IDEA 右侧的 Maven 面板里点一下刷新按钮那个循环箭头图标或者执行mvn clean compile观察输出如果警告消失了说明配置生效。如果还在检查一下是不是父 pom 里用了configuration硬编码了 1.5这种情况下 properties 可能覆盖不了需要改用方案二直接配置插件。4.4 第四步验证字节码版本编译完成后可以验证一下生成的 class 文件到底是什么版本javap -verbose target/classes/你的类名.class | grep major versionmajor version 和 Java 版本的对应关系是52 对应 Java 855 对应 Java 1161 对应 Java 1765 对应 Java 21。如果显示 49那就是 Java 5说明配置还没生效。这个验证步骤很多人会跳过但它能帮你确认警告消失和实际生效是两回事。有时候警告被抑制了但字节码版本还是老的这种假修复更危险。5. 那些年我踩过的坑5.1 改了 properties 还是报 1.5有一次我明明在 pom 里加了maven.compiler.source11警告还是顽固地出现。查了半天发现父 pom 里是这样配的plugin artifactIdmaven-compiler-plugin/artifactId configuration source1.5/source target1.5/target /configuration /plugin父 pom 用了configuration硬编码这种情况下子项目的 properties 优先级不够覆盖不了。解决办法是在子项目的 pom 里显式重新配置这个插件把 source/target 写死成新版本。5.2 IDEA 缓存导致的幽灵警告还有一种情况pom 改对了mvn compile也没警告了但 IDEA 的 Build 输出里还是老警告。这通常是 IDEA 的缓存没刷新。解决办法是File - Invalidate Caches - Invalidate and Restart重启后一般就好了。5.3 多模块项目的配置位置多模块项目里properties 应该配在父 pom里这样子模块自动继承。如果每个子模块单独配维护起来很痛苦。但要注意如果某个子模块需要不同的 Java 版本比如一个模块要用 8另一个要用 17那就在子模块里单独覆盖。5.4 source 和 target 不一致的坑有人为了兼容老环境把 source 设成 8target 设成 11。这种配置下编译器允许你用 Java 8 的语法但生成 Java 11 的字节码。听起来很美好实际上可能导致运行时行为不一致因为某些 API 在 8 和 11 之间是有变化的。最佳实践是 source 和 target 保持一致需要兼容低版本就都设低需要新特性就都设高。6. 常见问题速查现象可能原因解决方向警告反复出现父 pom 硬编码了 1.5子项目显式覆盖插件配置mvn 编译正常IDEA 还警告IDEA 缓存或独立配置清缓存 检查 Project Structure改了 properties 无效插件版本太老不识别属性升级插件到 3.0编译报不支持 lambdasource 还是 1.5确认 effective-pom 里的实际值运行报 UnsupportedClassVersionErrortarget 低于依赖要求提高 target 到依赖要求的版本中文注释乱码没配 encoding加 project.build.sourceEncoding7. 关于 Java 版本选择的一点个人看法处理完这个警告之后很多人会纠结到底该把 source/target 设成哪个版本我的经验是跟着项目实际运行环境走而不是跟着你本地的 JDK 走。如果你本地装了 JDK 21但生产环境是 JDK 8那把 source/target 设成 21 就是给自己挖坑——本地编译通过部署上去直接UnsupportedClassVersionError。比较稳妥的做法是先确认生产环境的 JDK 版本然后把 source/target 设成那个版本。如果生产环境短期内不会升级就别贪图新语法。如果生产环境已经是 17 或 21那就大胆用新特性同时把编译插件的 release 参数也用上plugin artifactIdmaven-compiler-plugin/artifactId version3.13.0/version configuration release17/release /configuration /pluginrelease是 Java 9 之后引入的参数它比 source/target 更严格——不仅控制语法和字节码版本还会校验你调用的 API 是否真的存在于目标版本中。用release能避免编译通过但运行报 NoSuchMethodError的尴尬。不过它要求编译时的 JDK 版本不低于 release 指定的版本所以 JDK 8 上用不了。这个警告本身不复杂但它背后牵扯出的IDEA 与 Maven 双配置父 pom 继承字节码版本验证这些点才是真正值得花时间搞清楚的东西。下次再看到类似的编译警告别急着搜怎么消除警告先想想为什么会有这个警告往往能顺藤摸瓜发现更多配置层面的问题。