一、异常其实就是将问题封装成对象并抛给调用者,异常的出现是为了提高程序的健壮性而将问题描述出来。
java分两个时期,一个叫编译时期,一个叫运行时期,编译时期就是说检查语法错误,也就是源代码有没有写错,如果源代码没写错,生成的.class文件在运行时期出错,这些情况就叫异常。
二、新建两个类,类名为ExceptionsDemo和Account,使用抛出异常的方式来处理异常。
1、在Account这个类中写一个“取钱”的功能
package introduction8; /*导入包为 * import java.sql.Connection; * 将Connection改为*后,这样就能一次性将sql这个包中的所有类 */ import java.sql.Connection; import java.sql.DriverManager; public class Accout { /* 在取钱之前,程序要访问数据库,提供账号信息、余额进行运算,然后判断能不能取出钱, * 因此需要先写一个能抛出异常,显示异常的功能, * 因为要建立一个数据库链接,使用mysql为例 */ public Connection getConn() { //Connection为引用型变量,默认值为空,用于与特定数据库进行连接, //他是一个接口,我们需要用到Connection链接 Connection conn = null; //定义连接数据库需要用到的参数 /*因为使用mysql数据库,所以使用jdbc,表示java数据库连接, * 是一种用于执行sql语句的java api,jdbc是java数据库的标准, * 提供了一种让java程序连接到数据库的机制,如果要使用jdbc连接到数据库, * 必须要使用jdbc驱动程序。 * (本机还未安装数据库,此处目的是为了演示异常,所以运行时会报异常) */ String url = "jdbc:mysql://localhost:3306/"; String user = "user"; String password = "code"; //Connection是一个静态方法,所以能够直接调用,创建数据库连接 conn = DriverManager.getConnection(url, user, password); return conn; } public void withdraw(int money) { } }
在eclipse中conn = DriverManager.getConnection(url, user, password);代码报错,
这里会报异常是因为Connection接口中有检查异常的机制,所以此处报出了sql异常
2、因为在getConn方法中有异常所以,在这个方法上要有throws声明出来,不然编译会失败,声明的目的是为了让调用这个getConn方法的人去处理,如果调用者也不处理的话,编译还是会失败的,在eclipse中鼠标移动到报错的代码上,会给出上图中两次解决方式(throws抛出异常,try/catch捕获并处理异常),这里选择第一种,直接抛出异常,让调用者自己解决。
3、选择抛出异常后在其它方法中调用,直接调用时会报异常,这就是前面提到的,如果调用者不处理的话,编译还是会报错。然后继续给调用的方法声明抛出异常。
4、在ExceptionsDemo类中调用
package introduction8; /* * 运行时会发生的问题分两类: * 1、exception异常: * 这种异常是可处理的,java虚拟机是用来解释并执行java程序的应用软件, * 这种是异常直接从java虚拟机发生的,是java虚拟机在运行过程中发生的问题, * 并告诉给使用者,对异常可以进行针对性处理。 * exception异常分两种: * a、编译时检查的异常,先检查语法的问题,语法都对的情况下再检查语法的安全问题。 * 对于编译时被检查的异常,功能如果有问题,当功能中又未声明的话,就会报错并且不会让程序执行通过。 * b、运行时异常,运行时异常编译器是不检查 * 如果代码中有零做为除数,编译时是不会检查该异常的,运行时才会报错,也就是说除数为零,代码的语法 * 和功能是没有问题的,只不过传的参数有问题。另外就是数值角标越界的情况,例如数值的长度为3, * 角标就是0、1、2这3个数,想访问角标为3的元素,编译时不会报错,运行时报错,因为3这个元素根本不存在。 * 2、Error错误: * Error发生是不处理的,error是由系统底层发生的,底层告诉了java虚拟机的,java虚拟机告诉使用者, * 例如内存溢出,一旦发生error了,必须修改代码,对异常本身不做针对性处理。 */ //因为用的IDE集成开发环境,都是可以检查编译时异常,异常的部分会先红色波浪线和红叉图标 public class ExceptionsDemo { public static void main(String[] args) { Accout acc = new Accout(); acc.withdraw(100); } }
调用后传参仍然报异常:
继续选择声明异常,点击运行,控制台提示异常
三、使用try/catch捕获异常
package introduction8; import java.sql.SQLException; /* * 运行时会发生的问题分两类: * 1、exception异常: * 这种异常是可处理的,java虚拟机是用来解释并执行java程序的应用软件, * 这种是异常直接从java虚拟机发生的,是java虚拟机在运行过程中发生的问题, * 并告诉给使用者,对异常可以进行针对性处理。 * exception异常分两种: * a、编译时检查的异常,先检查语法的问题,语法都对的情况下再检查语法的安全问题。 * 对于编译时被检查的异常,功能如果有问题,当功能中又未声明的话,就会报错并且不会让程序执行通过。 * b、运行时异常,运行时异常编译器是不检查 * 如果代码中有零做为除数,编译时是不会检查该异常的,运行时才会报错,也就是说除数为零,代码的语法 * 和功能是没有问题的,只不过传的参数有问题。另外就是数值角标越界的情况,例如数值的长度为3, * 角标就是0、1、2这3个数,想访问角标为3的元素,编译时不会报错,运行时报错,因为3这个元素根本不存在。 * 2、Error错误: * Error发生是不处理的,error是由系统底层发生的,底层告诉了java虚拟机的,java虚拟机告诉使用者, * 例如内存溢出,一旦发生error了,必须修改代码,对异常本身不做针对性处理。 */ //因为用的IDE集成开发环境,都是可以检查编译时异常,异常的部分会先红色波浪线和红叉图标 public class ExceptionsDemo { public static void main(String[] args){ Accout acc = new Accout(); try { /*把可能出现异常的代码反正try/catch这个大括号里面, * 如果try里面的语句有异常,就回去执行catch里面的语句 */ acc.withdraw(100); } catch (SQLException e) { //将异常信息封装成对象并打印 e.printStackTrace(); } } }
运行后的结果:
如果想自定义只打印错误信息:
四、catch不能离开try单独使用。
try语句可以没有catch,当try语句不能单独执行,如果没有catch就必须要与finally一起使用。
五、finally{}放在finally中的语句一定会被执行
六、try是如何工作的?
1、在try中添加如下两行代码,以便于我们能直观的看到try是如何运行的
结果:
直接跳过打印“执行withdraw”这条命令语句,执行catch和finally中的语句,这是因为try中有异常
2、注释未处理前报异常的代码
点击执行:
跳过了catch中的语句,只执行了try和finally中的语句,这是因为try中没有异常
7、try与finally一起使用,没有catch
这是在不一定要处理异常,但是有资源需要释放的情况下使用。
注释掉catch,然后运行
运行成功:
finally语句块中可以放释放资源的语句,例如断开数据库连接,有时候程序出现异常,资源是来不及释放的,而如果把资源放在finally中,就可以得到释放,因为finally中的语句是肯定会被执行的。