面向对象【异常处理】

面向对象【异常处理】

在学习异常这一阶段过程中,为了方便记忆和理清思路,画了一个思维导图,一遍能够较快的形成知识框架。
在这里插入图片描述

1、异常(一)

1.1、什么是异常?

Java运行期间发生的问题就是异常。

1.2、异常和错误的区别

异常:

程序发生异常时通常可以有针对性的处理方式。

错误:

程序发生错误,一般不会有针对性的处理方式。错误往往都是系统级别的问题,都是JVM所在系统发生并反馈给JVM的,无法针对处理,只能修正代码

1.3、异常发生的原因

  • 用户的非法操作;
  • 程序员编写代码时的不恰当设计
  • 来自于硬件设备故障。比如:网络通信是连接中断,或者JVM内存溢出等。

1.4、异常的分类

编译时(检查)异常:

要么声明,要么捕捉

运行时异常:

不需要捕捉或声明。
要声明也可以,如果声明了,无外乎就是让调用者给出处理方式。

1.5、异常的控制流程

方法栈遇到问题,异常处理的三种方式:

  1. 方法本身直接抓捕异常,不让这个“异常”对象沿着方法调用栈,继续向下传递;
  2. 方法本身直接抓捕异常,并继续让这个“异常”对象沿着方法调用栈,继续向下传递;
  3. 不去抓捕抓捕异常,就让这个“异常”对象沿着方法调用栈,继续向下传递,并且让方法从方法栈中直接弹出;

1.6、自定义异常

之前的几个异常都是java通过类进行的描述。并将问题封装成对象,异常就是将问题封装成了对象。这些异常不好认,书写也很不方便,能不能定义一个符合我的程序要求的问题名称。既然JDK中是使用类在描述异常信息,那么我们也可以模拟Java的这种机制,我们自己定义异常的信息,异常的名字,让异常更符合自己程序的阅读。准确对自己所需要的问题进行类的描述

自定义异常注意事项:

  • 所有的异常必须是Throwable的子类
  • 如果想编写一个可以自动被异常处理或声明规则强制的检查异常,就需要继承Exception
  • 如果想编写一个运行时异常,就需要继承RuntimeException

1.7、异常的继承体系

在这里插入图片描述

1.8、捕获、声明异常

捕获:

Java中对异常有针对性的语句进行捕获。

捕获格式:

try
{
	//需要被检测的语句。
}
catch(异常类 变量)//参数。
{
	//异常的处理语句。
}
finally
{
	//一定会被执行的语句。
}

注意:

return不管是在try语句块中还是在catch语句块中,再执行这个return之前,都先执行finally语句块,必须进入到try语句块才会执行finally语句块。

声明(throws):

将问题标识出来,报告给调用者

如果函数内通过throw抛出了编译时异常,而没有捕获,那么必须通过throws进行声明,让调用者去处理。

如果一个方法没有捕获一个检查性异常,那么该方法就要使用throws关键字来声明;

一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。

throw和throws的区别:
  • throw用在函数内。throws用在函数上
  • thorw抛出的是异常对象。throws用于进行异常类的声明,后面异常类可以有多个,用逗号隔开。
什么时候需要声明?
  • **继承Exception,必须要throws声明。**一声明就告知调用者进行捕获,一旦问题处理了调用者的程序会继续执行
  • **继承RuntimeExcpetion,不需要throws声明的。**这时调用是不可能编写捕获代码的,因为调用根本就不知道有问题。一旦发生NoAgeException,调用者程序会停掉,并有jvm将信息显示到屏幕,让调用者看到问题,修正代码

2、异常(二)

2.1、经典案例介绍

老师电脑讲课

两个对象

​ 老师:

​ 属性:姓名。

​ 行为:讲课。

电脑:

​ 行为:运行。

考虑问题

  1. 电脑蓝屏–>异常。
  2. 电脑冒烟–>异常。

分析问题

讲课中蓝屏,问题可以临时解决,是冒烟问题没有直接处理,所以就使用throws声明。但是发现,这个问题不应该属于讲课的问题。调用讲课方法的调用者是处理不了这个冒烟问题的。该调用者能处理的应该是冒烟导致的课程进行不下去的问题。应该在列出一个异常,课时停止异常。

class LanPingException extends Exception{ //电脑蓝屏异常描述
	LanPingException()	{
		super();
	}
	LanPingException(String message)	{
		super(message);
	}
}
class MaoYanException extends Exception{ //电脑冒烟异常描述
	MaoYanException()	{
		super();
	}
	MaoYanException(String message)	{
		super(message);
	}
}

class NoPlanException extends Exception{ //课时无法进行异常描述
	NoPlanException()
	{
		super();
	}
	NoPlanException(String message)
	{
		super(message);
	}
}

class NoteBook  {  //描述电脑对象
	private int state = 2;
	public void run()throws LanPingException,MaoYanException//方法上可以通过throws声明多个异常。
	{
		System.out.println("笔记本电脑运行");
		if(state == 1)
			throw new LanPingException("电脑蓝屏了");

		if(state == 2)
			throw new MaoYanException("电脑冒烟了");
	}
	public void reset()
	{
		state = 0;
		System.out.println("电脑重启");
	}
}

class Teacher{ // 描述老师
	private String name;
	private NoteBook book;
	Teacher(String name)
	{
		this.name = name;
		book = new NoteBook();
	}
	//讲课。
	public void prelect()throws NoPlanException
	{
		/*
		调用到了声明异常的方法,在这里到底是捕获好呢?还是声明好呢?
		有具体的捕获处理方式吗?有,那就捕获,没有,那么声明。
		我可以处理,重启就可以了,重启是电脑的功能。
		*/
		try
		{
			book.run();//对于声明多个异常的方法,在处理,需要定义多个catch与之对应。
		}
		catch (LanPingException e)	{
			//重启。
			System.out.println(e.toString());//异常的名称+异常的信息。
//			e.printStackTrace();
			book.reset();
		}
		catch(MaoYanException e){
			System.out.println(e.toString());
			test();
			//冒烟问题没有解决,继续声明throws出去。	throw e;
			throw new NoPlanException(e.getMessage()+",课时停止");//异常转换。
		}
		System.out.println(name+"....讲课");
	}
	//留练习。
	public void test()
	{
		System.out.println("做练习");
	}
}
class ExceptionTest2 {
	public static void main(String[] args) 	{
		Teacher t = new Teacher("毕老师");
		try		{
			t.prelect()
		}
		catch (NoPlanException e)		{
			System.out.println(e.toString());
			System.out.println("换老师");
		}		
		System.out.println("Hello World!");
	}
}

2.2、finally关键字

概念:

有一些特定的代码无论异常是否发生,都需要执行。因为异常会引发程序跳转,导致有些语句执行不到。无法满足这个需求。异常捕获处理时java提供解决方案,finally就是解决这个问题的,这个代码块中存放的代码都是一定会被执行。

应用场景:

定义一个功能往数据库中添加数据。

void add(Data data)throws NoAddException
{
	//1、连接数据库。
	try{
	//2、添加数据。//添加数据时发生了异常情况。throw new SQLException();程序跳转,
        就执行不到断开连接。
		//而断开连接必须要执行,因为不执行,连接资源在浪费。
		//无论是否发生问题,都需要执行断开连接的动作,从而释放资源。
	}catch(SQLException e)
	{
		//解决数据库的问题。
		//同时将问题告诉调用者。
		throw new NoAddException();
	}
	finally
	{
		//3,断开连接。
	}
}

总结:finally到底什么时候用?

只要程序中使用到了具体的资源(数据库连接,IO资源,网络连接socket等)需要释放,都必须定义在finally中。你在定义程序,只要问题发生与否,指定程序都需要执行时,就定义finally中。包括return的内容也会直接执行

2.3、异常细节

2.3.1、try catch finally 组合方式

try catch组合 : 对代码进行异常检测,并对检测的异常传递给catch处理,异常捕获处理。

void show()//不用throws 
{
	try{
		throw new Exception();
	}catch(Exception e)
	{
//处理方式	
	}
}

try finally 组合:对代码进行异常检测,检测到异常后因为没有catch,所以一样会被默认jvm抛出。异常是没有捕获处理的。但是功能所开启资源需要进行关闭,所有finally。只为关闭资源。

void show()//需要throws 
{
	try{
	throw new Exception();
	}finally
	{
		//关闭资源
	}
}

try catch finally 组合:检测异常,并传递给catch处理,并定义资源释放。

2.3.2、异常在方法复写中细节

异常在继承或者实现中的使用细节:

  1. 子类覆盖父类方法时,如果父类的方法声明异常,子类只能声明父类异常或者该异常的子类,或者不声明越来越精细
  2. 当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集 越来越精细
  3. 当被覆盖的方法没有异常声明时,子类覆盖时无法声明异常的。

举例:父类存在这种情况,接口也有这种情况,

问题:接口中没有声明异常,而实现的子类覆盖方法时发生了异常,怎么办?

​  无法进行throws声明,只能catch的捕获。万一问题处理不了呢?catch中继续throw 抛出,但是只能将异常转换成RuntimeException子类抛出。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值