比如:以下代码中的“Exception”为什么不用import包:

  1. try {
  2. ....
  3. }
  4. } catch (Exception ex) {
  5. CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
  6. ServletUtils.writeJSON(response, result);
  7. return;
  8. }

简单直接的回答是:因为 Exception 这个类在 java.lang 包里,而 java.lang 包下的所有类,Java 会“自动导入”到你的每一个 .java 文件中,所以不需要你手动写 import。

下面给你掰开揉碎讲讲,顺便结合你的 PHP 背景对比一下:

1. 什么是 java.lang 包?

你可以把 java.lang 理解为 Java 的“生存必备核心包”。里面放的都是最最基础、每个 Java 程序都离不开的类,比如:

  • String(字符串)
  • System(系统类,比如 System.out.println)
  • Object(所有类的祖宗)
  • Exception / RuntimeException(异常体系)
  • Math(数学计算)
  • Thread(线程)

Java 的设计者觉得:“这些类太常用了,如果每个文件都要写 import java.lang.String; 那不得烦死?” 于是规定:编译器在编译时,会自动隐式地帮你加上 import java.lang.*;。

所以你写 catch (Exception ex) 的时候,编译器其实早就知道 Exception 是 java.lang.Exception 了。

2. 对比 PHP 你更容易理解

你在写 PHP 的时候,是不是也经常直接 throw new Exception('出错啦');,而没有在文件顶部写 use Exception; 或者 use \Exception;? 这是因为 PHP 的内置异常类默认就在全局命名空间里,PHP 解释器天然认识它。

Java 这里其实是一个思路,只不过 Java 是“把所有核心类规整到一个 java.lang 包里,然后让编译器自动导入这个包”,而 PHP 是“把它们扔在全局命名空间里直接可用”。殊途同归,都是为了让你少敲代码。

3. 什么时候才需要 import 异常?

如果你 catch 的不是 Exception(它是顶层的父类,在 lang 包),而是其他具体异常,那就得导包了。比如:

  1. // 需要手动 import,因为 IOException 在 java.io 包里
  2. import java.io.IOException;
  3. try {
  4. file.read();
  5. } catch (IOException e) { // IOException 不在 java.lang 里,必须 import
  6. e.printStackTrace();
  7. }

或者你在用芋道(Yudao)框架里的自定义业务异常,比如 ServiceException,那就得 import cn.iocoder.yudao.framework.common.exception.ServiceException;,因为你的业务异常肯定不在 java.lang 里。

4. 总结一下

  • 在 java.lang 包里的类:不用 import,直接用(包括 Exception、String、Integer 等)。
  • 不在这个包里的类:必须 import 全类名,或者用 IDE(如 IDEA)的自动修复功能帮你导。

这也是为什么你在 Spring Boot 项目里,看到满屏的 String、Exception 都没有 import 语句,但一用到 List、HashMap 或者 UserService 就得导包的原因(List 在 java.util 包里,不在 lang 包)。

一句话记忆:Java 的 lang 包,就是“不用打招呼就能直接用”的亲儿子包。