try-catch
是 Java 和许多其他编程语言中用于异常处理的关键字组合,它允许程序员优雅地捕获和处理运行时可能出现的错误。以下是 try-catch
结构的详细说明:
结构:
try { // 有可能抛出异常的代码块 // 这里可以调用方法、执行操作等 riskyOperation(); } catch (SpecificExceptionType1 e) { // 处理 SpecificExceptionType1 类型异常的代码块 // 可以访问到异常对象 e,通过 e.getMessage(), e.printStackTrace() 等方法获取异常信息 System.out.println("Caught Exception Type 1: " + e.getMessage()); } catch (SpecificExceptionType2 e) { // 处理 SpecificExceptionType2 类型异常的代码块 System.out.println("Caught Exception Type 2: " + e.getMessage()); } finally { // 无论是否发生异常,都会执行的代码块 // 通常用于资源清理,如关闭文件、数据库连接等 cleanupResources(); }
解释:
try
块:包裹可能会抛出异常的代码。当try
块中的代码执行时,如果出现了异常(例如除数为零、文件未找到等),控制权将立即转到相应的catch
块。catch
块:每一个catch
块都与一个或一类异常类型相关联。当try
块中的代码抛出与catch
块声明的异常类型相匹配的异常时,与之关联的catch
块将被执行。在catch
块中,可以访问到异常对象,进而获取异常的详细信息。finally
块(可选):无论try
块中是否抛出了异常,以及是否有与之匹配的catch
块,finally
块中的代码总会被执行。通常用于资源回收、关闭打开的文件、数据库连接等操作,确保无论程序运行结果如何,都能正确释放资源。
示例:
try { int denominator = 0; int result = 10 / denominator; // 这将抛出 ArithmeticException } catch (ArithmeticException e) { System.out.println("Divide by zero error occurred: " + e.getMessage()); } finally { System.out.println("Finally block executed."); }
在这个例子中,尝试除以零会抛出 ArithmeticException
,这个异常会被相应的 catch
块捕获并处理,然后执行 finally
块中的代码。
多重捕捉:
在Java中,可以使用多重 catch
子句来捕获不同类型的异常。这样,可以根据异常的不同类型执行不同的处理逻辑。下面是一个使用多重 catch
的示例:
try { // 可能抛出多种类型异常的代码 File file = new File("non_existent_file.txt"); FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); String line = br.readLine(); } catch (FileNotFoundException e) { // 处理找不到文件异常 System.out.println("File not found: " + e.getMessage()); } catch (IOException e) { // 处理读取文件时发生的其他IO异常,如读取错误、缓冲区溢出等 System.out.println("An IO error occurred: " + e.getMessage()); } finally { // 清理资源,如关闭文件流 try { if (br != null) { br.close(); } } catch (IOException ex) { System.out.println("Error closing the reader: " + ex.getMessage()); } }
在上述代码中,try
块中包含了可能导致 FileNotFoundException
和 IOException
的代码。当出现 FileNotFoundException
时,第一个 catch
子句会被执行;如果发生了 IOException
但不是 FileNotFoundException
(例如读取过程中出现问题),则第二个 catch
子句会被执行。
需要注意的是,Java 7及更高版本引入了一种更简洁的异常处理方式,即使用一个多异常捕获的 catch
子句,可以捕获并处理多种类型的异常,如下所示:
catch (FileNotFoundException | IOException e) { System.out.println("An error occurred: " + e.getMessage()); }
这种方式可以合并处理同类或继承关系中的多种异常类型。但是,如果需要针对每种异常采取不同的处理措施,还是需要分开使用多个 catch
子句。
附:自定义异常
上面提到:如果抛出异常对象必须是异常类的子类(❌throw new String(”ssdf“)),但是现在想自定义一个怎么办呢?
1、为什么需要自定义异常类
Java中不同的异常类,分别表示着某一种具体的异常情况。那么在开发中总是有些异常情况是核心类库中没有定义好的,此时我们需要根据自己业务的异常情况来定义异常类。例如年龄负数问题,考试成绩负数问题,某员工已在团队中等。——可以通过异常名称就能直接判断此异常出现的原因,因此有必要不满指定条件时,通过此异常类判断出具体的异常问题
2、如何自定义异常类
- 继承于现有的异常体系:
java.lang.Exception
、java.lang.RuntimeException
- 通常提供几个重载的构造器:无参构造、(String message)构造器
- 提供一个全局常量:声明为static final long serialVersionUID
3、如何使用自定义异常类
- 在具体代码中,满足指定条件的情况下,只能手动使用"throw 自定义异常类的对象"方式,将异常对象抛出【生成异常对象,手动抛】
- 如果是非运行时异常,必须要处理:try-catch、throws
自定义异常类,并手动抛出异常对象→处理异常
//自定义异常类 class MyException extends Exception { static final long serialVersionUID = 23423423435L; private int idnumber; public MyException(String message, int id) { super(message); this.idnumber = id; } public int getId() { return idnumber; } }
public class MyExpTest { public void regist(int num) throws MyException { if (num < 0) throw new MyException("人数为负值,不合理", 3);//手动抛出异常对象 else System.out.println("登记人数" + num); } public void manager() { try { regist(100);//执行会产生异常对象的代码,就需要进行异常处理 } catch (MyException e) { System.out.print("登记失败,出错种类" + e.getId()); } System.out.print("本次登记操作结束"); } public static void main(String args[]) { MyExpTest t = new MyExpTest(); t.manager(); } }