程序设计进阶
1.引入异常
- 编译错误大部分只是代表着存在语法错误,并不是异常
- Java字节码运行中会涉及到字节码校验器,此时把代码的错误信息返回提示消息
- 异常的最高父类是 Throwable ,在java.lang 包下
- Throwable 类的构造方法主要是:
- public Throwable() 构造一个对象,其错误信息串为 null
- public Throwable() 构造一个对象,其错误信息串为 message
Throwable 类的方法主要有:
方法 | 说明 |
---|---|
public String getMessage() | 返回对象的错误信息 |
public void printStackTrace() | 输出对象的跟踪信息到标准错误输出流 |
public void printStackTrace(PrintStream s) | 输出对象的跟踪信息到输出流 s |
public String toString() | 返回对象的简短描述信息 |
- Throwable 类的子类有 Error 错误和 Exception 违例
- Error错误并不能通过程序代码来解决问题,但是Exception违例基本是程序员在编写代码时所造成的问题,所以往往我们会将 Error 设为天灾,Exception 设为人祸
2.异常处理机制 – 捕获
-
异常处理,就是当程序运行出错的时候的应对措施
-
Java异常处理机制中仍体现了面向对象的思想
- 如果程序执行时出现异常,会自动生成一个异常类对象,这个异常对象将被提交给Java运行时系统,那么这个过程就成为抛出异常
- 当 Java 运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程就是捕获异常
- 如果 Java 运行时系统找不到可以捕获异常的方法,那么运行时系统将终止,相应的 Java 程序也会退出
- 程序员之只能处理违例(Exception),而对错误(Error)无力回天,类似天灾人祸。
-
异常处理机制明确提出需要有代码来处理异常,出现异常,系统就会自动生成一个异常类对象,这个异常类对象是系统是自动生成的,程序员无需创建
捕获异常的基本结构:
try{
// 有异常出现的语句,无异常语句也可以放在这个语句块中
}catch(ExceptionClass e){
// 当产生 ExceptionClass 类型异常时的处置代码
}[catch(ExceptionClass2 e){
// 当产生 ExceptionClass2 类型异常时的处置代码
}catch(ExceptionClassN e){
// 当产生 ExceptionClassN 类型异常时的处置代码
}]
-
try 和 catch 是关键字,用来处理异常
-
注意:catch 语句块里面不能为空,空着代表捕获异常,不做任何处理
-
try
- 将可能会出现异常的代码放在 try 代码块中
-
如果 try 语句块中发现异常,那么剩下的语句就不再执行
-
catch
- 在 catch 语句块中式对异常对象进行处理的代码
- 每个 try 语句块可以伴随一个或多个 catch 语句,用于处理可能产生的不同类型的异常对象
- 通过 getmessage() 获取异常信息或者 printStackTrace()来跟踪异常信息
String names[] = {"小凳子", "小椅子", "小桌子"}; try { for (int i = 0; i < 4; i++) { System.out.println(names[i]); } System.out.println("over"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e); }
- 注意:当执行 System.out.println(names[3]) 出现异常后,那么剩下System.out.println(“over”) 将不会执行。 一旦出现异常,后面的代码就会忽略掉,但如果是将System.out.println(“over”) 语句放到 catch 语句块之后,那么处理完异常,程序还是会继续往后运行的
-
finally关键字
- finally 关键字主要和捕获异常的 try - catch语句一起使用,finally语句块中的内容表示无条件执行的部分,不管程序有没有异常都会执行的部分
try{ // 可能产生异常的代码 }catch( ExceptionClass1 e ){ // 当产生 ExceptionName1 类型异常时的处置措施 }catch( ExceptionClass2 e ){ // 当产生ExceptionName2型异常时的处置措施 }[finally{ // 无条件执行的语句 }]
- finally 语句放在 try - catch 的后面
- 这个语句不是一定非要写的,finally 语句和 catch 语句至少二选一即可
- 资源释放非常适合放着finally语句中
- finally语句后面的花括号不能省略
- final finally finalize的区别是什么
- final 是关键字,用来修饰属性、方法、类
- finally 是关键字,用来配合异常机制处理,该修饰语句无论有没有异常都会执行
- finalize 不是关键字,是根父类中的一个方法而已,也是java垃圾回收机制中进行资源释放发方法
-
RuntimeException
- 是所有运行时异常的父类
- 这些异常有很多在编译时会提示需要进行异常处理,否则编译将不能通过
3.异常处理方式 – 抛出
-
这是异常的另一种处理方式,使用关键字throws
-
异常抛出,主要在方法声明部分进行使用
-
throws 抛出的异常可以没有,也可以是很多个(声明方法时可以不抛出异常,也可以抛出任意多个)
[public|protected|private] 返回类型 方法名(参数列表) throws 异常类[, 异常类2, ..., 异常类n]{ // 方法体 }
-
发生异常时,可以不再方法中对异常进行处理,可以把这个异常交给方法的调用者来处理(比如家里的冰箱坏了,可以自己来修理,修理不了,也可以上报给卖冰箱的商家处理,商家处理不了,就会继续往上上报问题…)
-
主动抛出异常
- 当系统发现异常,会自动生成一个异常对象,再交给运行时系统,这是抛出异常,主动抛出异常就是不用系统自己生成异常对象,而是在我们写代码的时候,对于可能出现的异常,自己创建异常对象将其抛出
- throw 和 throws 的区别在于,前者只能抛出一个确切的异常类对象,但是后者可以抛出多个异常类,而不是 new 的对象
throw new 异常类(message); public void method1() throws Exception{ String names[] = {"小凳子", "小椅子", "小桌子"}; for (int i = 0; i < 4; i++) { if(i > names.length-1){ throw new ArrayIndexOutOfBoundsException("数组下标越界异常:数组元素提取下标为 " + i + ",超出数组取值范围!"); } System.out.println(names[i]); } System.out.println("over"); } public void method2(String a,String b){ double c = 0.0; try{ int a1 = Integer.parseInt(a); if(a1 == 0){ throw new RuntimeException("第一个参数为 0 ,除法计算永远都是零"); } int b1 = Integer.parseInt(b); if(b1 == 0){ throw new ArithmeticException("除数不能为零"); } c = a1 / b1; }catch(ArithmeticException e){ System.out.println(e); }catch(NumberFormatException e){ e.printStackTrace(); }catch(RuntimeException e){ System.out.println(e.getMessage()); } System.out.println(c); }
- hrow 可以和 throws 配合使用,也可以和 try-catch 配合使用。
- 注意:throw 之后的只能是异常对象,不能是其他对象,也就是说不能这样写 throw new String(“错误信息”)
-
方法重写的深入
-
- 方法名、返回类型、参数列表必须相同,返回类型发特殊情况是可以返回父类的子类,存在继承关系的子类型
- 方法的修饰符范围可以大,但是不能小
- 子类重写父类抛出多个异常类,可以只抛出父类中的一个异常类,不抛出异常类也是可以的,但是抛出的异常类不能大于父类抛出的异常类
- 总结而言:当子类重写父类方法时,需要考虑抛出的异常类,可以相同或是子类,但是不能更大
-