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后面,不能在catchfinally之间存在其他语句
如: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("我好帅啊~~");
}
}
}
posted @   Lz_蚂蚱  阅读(54)  评论(0编辑  收藏  举报
(评论功能已被禁用)
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起