欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第八章 异常(20210630)

程序员文章站 2022-06-15 22:50:33
...

异常定义

程序正在编译或执行时,发生不可预料的问题,不严重可以通过修改代码解决。(拔网线)

异常的继承关系

父类Throwable

  • 子类Error
    程序正在编译或执行时,发生不可预料的问题,严重到不可以通过修改代码解决(砸碎电脑)。
  • 子类Exception

异常的种类

  • 未捕获异常:编译可以通过,运行时被JVM抓住报错
    RuntimeException及其子类
  • 捕获异常:编译时就报错,不能运行,必须处理
    除了RuntimeException类的其他异常类

异常的处理机制

1.try catch --可以处理所有异常
语法:

	try{
	//可能会产生异常的代码块
	m=0;
	int s = 10/m;
	}catch(可能发生异常的类名  对象名){
	//发生异常之后,处理异常的代码块
	}
  • try中写可能会产生异常的代码块,如果发生异常直接将产生的异常对象以及代码的执行权交给catch代码块。
  • 一个try catch 里可以写多个catch,需要按照Exception的继承关系排列(从子到父)。异常发生时,只执行当前对应的catch代码块中的内容,其他的catch都不执行。
	try {
		int k = new Scanner(System.in).nextInt();
		int res = 10/k;
	}
	catch(Error e) {
	}
	catch(ArithmeticException e) {//被除数为0异常
	}
	catch(InputMismatchException e) {//数据类型不匹配异常
	}
	catch(RuntimeException e) {//父类
	}
	catch(Exception e) {//父类爸爸
	}
	catch(Throwable obj) {//父类爷爷
	}

2.throws–只能处理捕获异常(编译异常),不能处理未捕获异常(运行异常)
语法:
在发生异常的语句 所在的方法定义形参列表后 加 throws + 抛出的异常类名

public static void main(String[] args) throws IOException{
	System.out.println("请输入");
	int m = System.in.read();//IOException 捕获异常
}
  • 处理原理:将异常扔给上级主调方法,直到JVM
  • throws后也可写多个异常类名,但也要按照继承关系 从子到父。

finally关键字

由于一旦发生异常,异常后的代码将无法执行,但有些代码我希望它即使发生异常也要执行,那么就把这些代码写到finally中。

  • 一个try只能跟一个finally。
    原因:第一个finally后的代码就不会被执行到
  • finally的代码原则上在最后执行,但try-catch代码块中有return时,先执行finally代码,再执行return。
    原因:return后的代码不被执行
	public static void main(String[] args) {
		int x =new TestFinallyAndReturn().test();//间接调用
		System.out.println(x);
	}
	int test() {
		try {
			System.out.println("请输入一个除数try:");
			int k = new Scanner(System.in).nextInt();
			int res = 10/k;
			return res;
		}
		catch(Exception e) {
			System.out.println("catch");
			return 0;
		}
		finally {
			System.out.println("finally执行");
		}
	}
输出结果:
请输入一个除数try:
5
finally执行
2
  • 只有在finally之前有System.exit(int)时,finally代码不执行。
    原因:System.exit(int)关闭JVM
public static void main(String[] args) {
		int x =new TestFinallyAndReturn().test();//间接调用
		System.out.println(x);
	}
	int test() {
		try {
			System.out.println("请输入一个除数try:");
			int k = new Scanner(System.in).nextInt();
			int res = 10/k;
			System.exit(1);//关闭  JVM java虚拟机
			return res;
		}
		catch(Exception e) {
			System.out.println("catch");
			return 0;
		}
		finally {
			System.out.println("finally执行");
		}
	}
输出结果:
请输入一个除数try:
5

throw关键字

抛出异常
1.理解throw
在try-catch中,发生异常时,实际是由JVM创建了一个异常类,并由throw关键字将异常对象抛给相应的catch。此处也可以理解为什么catch语法中括号内写的是“类名 对象名”,可以将其理解为传参。

	try {
		String s = null;
		s.equals("111");
		//JVM立刻创建一个异常类的对象 并由throw关键字  将此异常对象抛给对应的catch
		//throw new NullPointerException()
		int k = 10/0;
		//JVM创建ArithmeticException类型对象 
		//throw new ArithmeticException();
	}catch(NullPointerException e) {
			
	}

2.应用:自定义异常

创建父类FireException继承 Exception,让FireException成为异常的子类。

public class FireException extends Exception{
	@Override
	public String toString() {
		return "着火了,拨打119";
	}
}

多态,分别定义Big Small 类,继承FireException。

public class BigFireException extends FireException{
	@Override
	public String toString() {
		//此处调用了父类的toString()方法
		//好处:当父类toString()方法返回值修改时,子类不必每个都修改。
		return super.toString() + "着大火了,快跑,沿着安全通道跑!!!";
	}
}

public class SmallFireException extends FireException{
	@Override
	public String toString() {
		return super.toString() + "着的是小火,用灭火器灭火,注意安全!!!";
	}
}
public class Boys {
	void smoke() throws SmallFireException ,BigFireException{
		System.out.println("******************");
		System.out.println("请选择您本次丢弃烟头的地点");
		System.out.println("1 水桶");
		System.out.println("2 柴火垛");
		System.out.println("3 鞭炮堆");
		System.out.println("******************");
		Scanner scan = new Scanner(System.in);
		int cmd = scan.nextInt();
		switch(cmd) {
		case 1:System.out.println("真好,真棒!!!");break;
		case 2:throw new SmallFireException();
		case 3:throw new BigFireException();
		default:System.out.println("您输入不存在");break;
		}
	}
}

上记代码中,在switch代码块的case2,case3 处,使用throw关键字抛出自定义异常

public class TestFireException {

	public static void main(String[] args)  {
		// TODO Auto-generated method stub
		Boys xiaoMing = new Boys();
		try {
			xiaoMing.smoke();
		}
		catch(Throwable e) {
			System.out.println(e.toString());
		}
//		catch(SmallFireException sfe) {
//			System.out.println(sfe.toString());
//		}
//		catch(BigFireException bfe) {
//			System.out.println(bfe.toString());
//		}
	}
}

问:为什么重写Throwable的toString方法而不是自己重新定义一个方法?
答:重写toString()方法时,在捕捉异常时,可以只写一个catch Throwable异常,异常对象可以调用toString()方法。但是,如果在子类BigFireException(SmallFireException)中重新定义一个方法,无法通过Throwable 的异常对象调用该子类自己的方法。

错误信息:The method toStringzidingyi() is undefined for the type Throwable