在Java中如何捕获异常_Java try catch基本用法解析

Java中try必须配对catch或finally,不可单独使用;可多catch按具体到宽泛顺序排列,或用try-with-resources自动管理资源;异常处理不应替代正常流程控制。

Java中try catch必须配对使用吗

不是必须写 catch,但必须有 catchfinally 之一。只写 try 会编译失败。

常见错误现象:error: 'try' without 'catch', 'finally' or resource declarations

  • try 后面可以跟一个或多个 catch(按异常类型从具体到宽泛排列)
  • 也可以只跟一个 finally(比如资源清理场景),但此时无法捕获异常,仅保证执行
  • JDK 7+ 支持 try-with-resources,自动关闭 AutoCloseable 资源,可省略 finally 中的 close() 调用

捕获多个异常时的顺序为什么不能乱

因为 Java 按照 catch 块从上到下的顺序匹配异常类型,一旦匹配成功就不再往下检查。如果宽泛类型(如 Exception)写在前面,后面具体的子类(如 NullPointerException)永远无法被捕获。

编译器会直接报错:error: exception NullPointerException has already been caught

  • 正确

    顺序:先 catch (IOException e),再 catch (Exception e)
  • 同一 catch 中可并列多个异常类型(JDK 7+):catch (IOException | SQLException e),但它们必须互不继承
  • 不要用 catch (Throwable t) 除非你明确要捕获 Error(如 OutOfMemoryError),否则可能掩盖严重问题

try catch会影响性能吗

不抛异常时,try 块本身几乎无运行时开销;但一旦抛出异常,栈遍历、异常对象创建、填充堆栈信息都会带来明显性能下降(比普通控制流慢 10–100 倍)。

  • 别用异常做流程控制(比如用 NumberFormatException 判断字符串是否为数字)
  • 日志中打印异常时,优先用 logger.error("msg", e) 而非 e.printStackTrace(),避免输出到标准错误流且不可控
  • 生产环境慎用空 catch(即 catch (Exception e) { }),它会静默吞掉所有线索
try (FileInputStream fis = new FileInputStream("data.txt")) {
    int b;
    while ((b = fis.read()) != -1) {
        System.out.write(b);
    }
} catch (IOException e) {
    System.err.println("读取文件失败:" + e.getMessage());
}

复杂点在于:异常类型判断依赖继承关系,而实际抛出的异常可能是运行时动态生成的(比如代理、反射、框架封装后的异常)。这时候光看 catch 的声明类型不够,得用 e.getClass().getName()e.getCause() 追踪真实源头。