Throwable
Throwable 类是 Java 语言中所有错误或异常的超类。
常用方法:
-
String getMessage()
返回此 throwable 的详细消息字符串 -
**void printStackTrace()
将此 throwable 及其追踪输出至标准错误流。 **
java异常
java中所有异常的超类Throwable, 其下有两个子类 Error 和 Exception
Error 和 Exception 的区别:
Error
- Error 是系统级错误,是Java运行环境内部错误或者硬件问题,不能通过程序来处理这样的问题,发生错误时程序退出运行。
- 它是Java虚拟机抛出的,比如虚拟机内存溢出等。
Exception
- Exception是程序需要处理的异常,由于程序设计的不完善(程序员逻辑问题)而出现的问题,程序必须进行处理,比如空指针异常,数组下标越界异常等。
- 通常程序中处理的异常都是Exception
Exception 的分类
1.编译时异常(检查异常)-- CheckedException
java 语言强制要求处理的所有非运行时异常,例如IOException ,SQLException
2.运行时异常(非检查异常 UnChecked) --RuntimeException,
RuntimeException一般是由于程序逻辑错误引起的,比如算术异常,空指针异常等待。
java两种异常处理机制
- java 中有完善的两种异常处理机制,可以捕获try-catch-[finally] 或者 抛出throws
- 捕获throws
- try{
代码片段;
}catch(XXXException e){
处理try中出现的XXXException的代码方案;
} [finally{}] finally是可选操作,当有finally时,finally中的代码一定会被执行
可以捕获一个超类的异常:
1.当try中出现了几种不同的异常,但是他们的解决办法相同
2.在最后一个catch处理捕获Exception可以避免因为一个未处理的异常导致程序中断。
需要注意的是:多个catch的异常之间若存在继承关系,一定要先捕获子类异常,再捕获超类异常,否则编译不通过。
异常之间没有关系捕获异常时可以随意声明位置
public class Test1_TryCatch {
public static void main(String[] args) {
System.out.println("程序开始...");
try{
/*
* 当JVM执行出现错误时,就会实例化对应问题的异常实例,并设置出错位置后将其抛出
* */
String str = null;//不初始化的话,直接编译报错:可能未初始化
str = "";
str = "abc";
System.out.println(str.length());//str为null时,不能调用方法和属性,否则报空指针异常。
System.out.println(str.charAt(2));//str为空串,没有下标为2的字符,报字符串下标越界异常:java.lang.StringIndexOutOfBoundsException
//报java.lang.NumberFormatException数字格式异常
System.out.println(Integer.parseInt(str));
//try语句中报错语句之后的代码都不会执行。
System.out.println("!!!");
//当try中代码不出错时,catch不执行。
}catch(NullPointerException e){
//定义try中出现空指针异常后的解决办法
System.out.println("空指针异常");
//catch 可以定义多个,针对try中不同的异常有不同的处理方式时可以分别捕获并处理
}catch(StringIndexOutOfBoundsException e){
System.out.println("字符串下标越界异常");
/*
* 通常情况下我们可以捕获一个超类的异常:
* 1.当try中出现了几种不同的异常,但是他们的解决办法相同
* 2.在最后一个catch处理捕获Exception可以避免因为一个未处理的异常导致程序中断。
* 需要注意的是:多个catch的异常之间若存在继承关系,一定要先捕获子类异常,再捕获超类异常,否则编译不通过。
* 异常之间没有关系捕获异常时可以随意声明位置
* */
}catch(Exception e){
System.out.println("404");
e.printStackTrace();//打印异常的具体信息
System.out.println(e.getMessage());//获取出现异常的原因描述:For input string: "abc"
System.err.println(e.getMessage());//获取出现异常的原因描述:For input string: "abc"(颜色发生变化)
}
System.out.println("程序结束!!!");
}
}
Finally
finally 是try-catch-finally 中的一块,他可以直接跟在try后面(很少这样用),或跟在最后一个catch之后。 finally可以保证只要程序执行到try当中,无论try里面的语句是否抛出异常,finally中的代码必定执行,(除直接退出程序外,如System.eixt(0)则不会执行finally中的代码),通常我们将释放资源这类操作放到finally中,比如IO操作后的关闭。
finally中的语句一定会执行,但是在try中已经将确定要返回的值x是基本类型,即使在finally中值被修改也不改变原先要返回的值。
如果要返回的值是引用类型则finally中改变值,最终返回的值将被改变
当finally中有return语句时,返回finally中的值,
当finally中没有return语句,return语句在finally语句之前,即使finally中对返回的变量值进行修改,也不会改变第一次return中的返回值
return 语句在finally语句之前也要先执行完finally中语句再结束程序,finally语句后的代码不再执行
常见面试题:
请分别说出final ,finally ,finalize(方法名)
final 可以修饰属性,方法,类。
final修饰属性为常量,初始化后不可被修改。
final修饰方法可被继承不能被重写。
final 修饰类不能被继承。
finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带着一个语句块,在系统不发生中断情况下,表示这段语句最终一定被执行,经常被用在需要释放资源,关闭文件,关闭数据库连接的情况下。
finalize是方法名,当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。
异常处理机制在IO中的 应用
/**
* 异常处理机制在IO中的应用
*
* @author yyc
* 2021/9/18 14:33
*/
public class Test3_Finally2 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("fos.txt");
fos.write(1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if (fos != null) {
//如果fos为null,则汇报空指针异常,即没有开流
fos.close();//fos的作用域只在try中,要实现finally中顺利关流,所有需要把声明放到try-catch-finally之前。
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
java 处理机制二:Throws
自动关闭特性:AutoCloseable
JDK7之后,推出了一个新特性,AutoCloseable 自动关闭特性
- 允许我们在IO操作中使用异常处理机制更简洁的完成最后的close()关流操作。
- 语法:
- try(定义需要在finally中调用close()方法关闭的对象){
-
IO操作
- }catch(XXXException){
-
...
- }
- 上述语法中在try的"()"中定义的并初始化的对象必须实现了java.io.AutoCloseable接口,否则编译不通过,javaIO中的流和
RandomAccessFile都已经实现了这个接口。
子类重写超类中含有Throws声明异常抛出的方法时对throws的几种特殊的重写规则。
①;子类可以抛出与父类抛出相同异常
②:重写父类的方法也可以不抛出异常
③:子类可以抛出超类方法的部分异常
④:子类可以抛出父类方法抛出的异常的子异常
⑤:子类不能抛出父类中没有抛出的异常
⑥:子类不允许抛出超类方法抛出异常的超类异常(子类抛出的异常不允许大于父类抛出的异常)
throw
throw关键字,用来对外主动抛出的一个异常。
通常以下两种情况,我们主动向外抛出异常:
- 1.当程序遇到一个满足语法,但是不满足业务要求(逻辑)时,可以抛出一个异常告知调用者。
- 2.程序执行遇到一个异常,但是该异常类不应当在当前代码片段被解决时可以抛出给调用者。(谁调谁解决)
throw 和 throws 的区别:
- 1.throw 的声明位置在方法体内,后面跟的是异常类的实例(对象)(new XXXException(”异常信息描述“)),只能有一个;
- throws 的声明位置在方法声明后,后面跟的是异常类名。
- 2.throw 后面只能抛出一个异常对象名,throws同时抛出多个异常时中间用“,”逗号隔开。
throw 和 throws 联系: - 1.如果方法中有throw 抛出的RuntimeException 及其子类对象,则方法声明上可以没有throws,(由该方法的调用者处理该异常),除此之外,方法声明上必须有throws
当我们调用一个含有throws声明异常抛出的方法时,编译器要求我们必须处理这个异常。否则编译不通过,处理方式有两种:
1.在当前方法上继续使用throws声明该异常并抛出给调用者解决。当异常发生在main方法中,我们可以在main方法声明后使用throws抛出该异常,但是main方法是程序的入口,不会再被调用,抛出去之后异常始终得不到处理。所以不建议main方法抛出异常。
2.使用try-catch方式捕获处理。
只有RuntimeException不需要手动抛出异常,其他异常抛出时要在方法上使用throws通知调用者。