Excepton异常类
异常结构
java.lang.Throwable 释义:可抛出、异常 |-----java.lang.Error:一般不编写针对性的代码进行处理。释义:错误、过失 |-----java.lang.Exception:可以进行异常的处理 释义:异常 |------编译时异常(checked) |-----IOException 释义:输入输出异常 |-----FileNotFoundException 释义:找不到文件异常 |-----ClassNotFoundException 释义:类无法加载异常/类文件未找到异常 |------运行时异常(unchecked,RuntimeException) |-----NullPointerException 释义:空指针异常 |-----ArrayIndexOutOfBoundsException 释义:数组索引越界异常 |-----ClassCastException 释义:类型转换异常 |-----NumberFormatException 释义:数字格式化异常 |-----InputMismatchException 释义:输入非数字异常 |-----ArithmeticException 释义:算数异常
1.运行时异常
指编译器不要求强制处置的异常,一般是指编程时的逻辑错误,应该积极避免其出现的异常。java.lang.RuntimeException
类及它的子类都是运行时异常。
2.编译时异常
指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求Java程序必须捕获或声明所有编译时异常。
常见异常
捕获异常的有关信息
与其他对象一样,可以访问一个异常对象的成员变量或调用它的方法。
- getMessage():获取异常信息,返回字符串。
- printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。返回void。
异常处理五个关键字
- 捕获异常
try:执行可能产生异常的代码
catch:捕获异常
finally:无论是否发生异常,代码总被执行
- 抛出异常
throw:异常的生成阶段;手动抛出异常对象
- 声明异常
throws:异常的处理方式;声明方法可能抛出的各种异常类
异常处理机制
如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
在方法声明中用throws
语句可以声明抛出异常的列表,throws
后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
声明抛出异常🌰:
public void readFile(String file) throws FileNotFoundException { ... // 读文件的操作可能产生FileNotFoundException类型的异常 FileInputStream fis = new FileInputStream(file); ... }
"throws + 异常类型"
写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws
后异常类型时,就会被抛出。异常代码后续的代码,就不再执行!
try-catch-finally
:真正的将异常给处理掉了。throws
的方式只是将异常抛给了方法的调用者。并没有真正将异常处理掉。
开发中如何选择使用try-catch-finally 还是使用throws?
如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中有异常,必须使用try-catch-finally方式处理。
执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
重写方法声明抛出异常的原则
重写方法不能抛出比被重写方法范围更大的异常类型。在多态的情况下,对methodA()方法的调用-异常的捕获按父类声明的异常处理。
public class A { public void methodA() throws IOException { ... } }
public class B1 extends A { /* 根据异常类结构可知,FileNotFoundException父类是IOException,子类B1重写父类的方法声明的异常范围并未 超出父类被重写方法声明的范围,所以不会报错。 */ @Override public void methodA() thorws FileNotFoundException { ... } }
public class B2 extends A { /* B2类继承A类,并重写A的mothodA()方法,父类A中methodA()方法声明的异常为IOException 而我们重写的方法中声明的是范围更大的异常类型,超出了父类方法声明的异常范围。从而报错。 */ @Override public void methodA() throws Exception { ... } }
自定义异常类
-
自定义异常类,必须继承 Exception (编译异常)或者 RuntimeException(运行异常)
-
自定义异常需要提供serialVersionUID
-
自定义异常类通常需要编写几个重载的构造器
-
自定义的异常通过throw抛出
-
自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。自定义异常类一般都是以Exception结尾,说明该类是一个异常类。
注意事项:
继承 Exception (编译异常):那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try-catch。
继承RuntimeException(运行异常:那么自定义的异常类就是一个运行期异常,无需处理,交给JVM处理。
举个🌰:
public class MyException extends Exception { static final long serialVersionUID = -7034897193246939L; public MyException(){ } public MyException(String msg){ super(msg); } }
异常使用中注意问题
1、throw 生成异常类对象抛出异常,是否需要声明抛出异常 throws + 异常类型 结果:如果throw new Exception;在try中就需要有catch进行异常匹配处理,若没有catch结构,就需要声明throws进行异常抛出,当throw new RunTimeException时就不用throws 进行抛出可以自动抛出到方法调用处,因为Exception内包含编译时异常,编译时异常需要先处理后才能编译
如:方法名() throws 异常类型{ throw new Exception; } public static void func() { try{ throw new Exception; // 此时创建的是Exception,包含了编译时异常,try没有catch对其进行处理,就需要throws进行异常抛出,否则报错 } finally{ System.out.println("B"); }
2、catch执行完是否直接执行finally 结论:是
如:catch(Exceptiob e){ } System.out.println("a"); // 不能输出,finally报错 finally{ }
3、try中异常下面的语句是否执行 结论:不会,会直接跳到异常对应的catch结构中
try{ method1(); //存在异常 下面可以有语句,但是不会执行,直接跳到对应的catch中 System.out.println("a"); } catch (Exceptiob e){ }
4、throw 创建异常对象下面是否可以存在语句 结论:不可以
如:throw new Exception; System.out.println("a"); // 不会输出,会报错不可以throw下方不可以有语句
结论:
1.当前try-catch-finally要结束之前会执行finally 2.调用方法存在异常,方法下可以有语句,但是不会被执行 如:method1();//存在异常 下面可以有语句,但是不会执行 System.out.println("a"); 3.如果存在finally只能跟在catch后面,不能在catch与finally之间存在其他语句 如:catch(Exceptiob e){ } System.out.println("a"); // 不能输出,finally报错 finally{ }
举个🌰:
自定义异常类
//public class CustomException extends Exception { public class CustomException extends RuntimeException { private static final long serialVersionUID = 7776961148544198687L; public CustomException(String message) { super(message); } }
/** * 如果有内部自定义的错误码及翻译,我们可以使用继承Exception的自定义异常 * 当被调用方法将异常抛到最上级方法,被捕获后可以根据自定义异常来响应相应的错误码和信息 * (异常使用方式根据实际场景来选取,此处仅作说明) * * @throws CustomException */ public void testExtendsException() throws CustomException { // 此时必须处理,throws或者try-catch,否则编译报错 throw new CustomException("继承Exception自定义异常"); } /** * 如果有国际化翻译的错误码,我们也可以使用继承RuntimeException的自定义异常 * 当异常抛出后,可以根据自定义异常的错误码来翻译成对应的提示信息 * (异常使用方式根据实际场景来选取,此处仅作说明) */ public void testExtendsRuntimeException() { // 此时不需要处理,编译也不会报错,只有在运行时才会抛出异常报错 throw new CustomException("继承RuntimeException自定义异常"); }
finally的使用
捕获异常的最后一步是同步哦finally
语句为异常处理提供一个统一的出口,使得在控制流转到程序的其它部分以前,能够对程序的状态作统一的管理。
不论在try代码块中是否发生了异常事件,catch语句是否执行,catch语句是否有异常,catch语句中是否有return,finally块中的语句都会被执行。
finally语句和catch语句是任选的。
🌰:
/* * try-catch-finally中finally的使用: * * * 1.finally是可选的 * * 2.finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中有 * return语句等情况。 * * 3.像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源的 * 释放。此时的资源释放,就需要声明在finally中。 * * * */ @SpringBootTest public class FinallyTest { @Test public void test2() { FileInputStream fis = null; try { File file = new File("hello1.txt"); fis = new FileInputStream(file); int data = fis.read(); while (data != -1) { System.out.print((char) data); data = fis.read(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fis != null) fis.close(); } catch (IOException e) { e.printStackTrace(); // 获取异常类名、异常信息,以及在程序中的位置 } } } @Test public void testMethod() { int num = method(); System.out.println(num); } public int method() { try { int[] arr = new int[10]; System.out.println(arr[10]); return 1; } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); return 2; } finally { System.out.println("我一定会被执行"); return 3; } } @Test public void test1() { try { int a = 10; int b = 0; System.out.println(a / b); } catch (ArithmeticException e) { e.printStackTrace(); // int[] arr = new int[10]; // System.out.println(arr[10]); } catch (Exception e) { e.printStackTrace(); } // System.out.println("我好帅啊!!!~~"); finally { System.out.println("我好帅啊~~"); } } }
本文来自博客园,作者:Lz_蚂蚱,转载请注明原文链接:https://www.cnblogs.com/leizia/p/16513578.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步