JavaSE:异常处理
概述
异常:在Java语言中,将程序执行中发生的不正常情况称为:“异常”(开发过程中的语法错误和逻辑错误不是异常)
Java程序在执行过程中所发生的异常事件可分为两类:
- Error:Java虚拟机无法解决的严重问题。一般不编写针对性的代码进行处理
- Exception:其他因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:空指针访问、试图读取不存在的文件、网络连接中断、数组角标越界
对于这些错误,一般有两种解决方法:一是遇到错误就终止程序的运行。另一种方法是由程序员在编写程序时,就考虑到错误的检测、错误消息的提示,以及错误的处理。
捕获错误最理想的是在编译期间,但又的错误只有在运行时才会发生。比如:除数为0,数组角标越界等
异常的分类
运行时异常
- 是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常。
- 对于这类异常,可以不做处理。
编译时异常
程序在运行时由于外界因素造成的一般性异常,编译器要求必须捕获或者声明所有编译时异常。
异常处理机制一:rty-catch-finally
异常的处理:抓抛模型
过程一:“抛” :程序在正常执行的过程中,一但出现异常,就会在异常代码处生成一个对应异常类的对象。并将此对象抛出。一但抛出对象以后,其后的代码不再执行。
过程而:“抓” :可以理解为异常的处理方式:
- try - catch - finally
- throws
结构
try {
//可能出现异常的语句
} catch (异常类型 变量名) {
//处理异常的方式;
}finally {
//一定会执行的语句
}
说明:
- finally 是可选的
- 使用try将可能出现异常代码包装起来,再执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch 中进行匹配。
- 一旦try中的异常对象匹配到某一个catch,就会进入catch中进行异常处理。一旦处理完成,就跳出当前的try-catch结构(再没有写finally 的情况下)。继续执行其后的代码。
- catch 中的异常类型如果没有子父类关系,则谁声明再上,谁声明在下无所谓。catch 中的异常类型如果满足子父类关系,则要求子类一定声明再父类的上面。否则报错。
- 常用的异常对象处理方式:
- String getMessage();
- printStrackTrace()
- 再try结构中声明的变量,出了try结构以后,就不能再被调用
补充:
-
finally 中声明的是一定会被执行的代码。不论在try代码块中是否发生了异常事件,catch语句是否执行,catch语句是否有异常,catch语句中是否有return,finally块中的语句都会被执行。
-
像数据库连接、输入输出流、网络编程Socket等资源,JVM 是不能自动的回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在finally 中。
使用
public class ExceptionTest1{
@Test
public void test1(){
String str = "123";
str = "abc";
try{
int num = Integer.parseInt(str);
System.out.println("hello world");
}catch(NumberFormatException e){
//常用的方法
//String.getMessage();
System.out.println(e.getMessage());
//printStackTrace();
e.printStackTrace();
System.out.println("出现数值转换异常");
}catch(NullPointerException e){
System.out.println("出现空指针异常");
}catch(Exception e){
System.out.println("出现异常");
}
System.out.println("hello");
}
}
异常处理机制二:throws + 异常类型
说明 :“throws + 异常类型” 写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。一旦当方法体执行时,出现异常,仍会再异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码后续的代码,就不再执行了。
与 try - catch -finally 不同的是:try - catch -finally 真正的将异常处理掉了,throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉。
public class ExceptionTest2{
public void method() throws FileNotFoundException,IOException{
File file = new file("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1){
System.out.println((char)data);
data = fis.read();
}
fis.close();
}
}
手动抛出异常
关于异常对象的产生:
- 系统自动生成的异常对象
- 手动的生成一个异常对象,并抛出(throw)
@Test
public int divide(int i,int j) throws Exception{
if(j != 0) {
return i / j;
}else {
//手动抛出异常对象
// throw new RuntimeException("您输入的数据非法!");
throw new Exception("您输入的数据非法!");
}
}
用户自定义异常
说明:
- 一般地,用户自定义异常类都是RuntimeException的子类。
- 自定义异常类通常需要编写几个重载的构造器。
- 自定义异常需要提供serialVersionUID(可以从继承的异常类中获取之后更改,UID要唯一)
- 自定义的异常通过throw抛出。
- 自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。
public class MyException extends Exception{
static final long serialVersionUID = -3387516421429948L;
public MyException() {
}
public MyException(String msg) {
super(msg);
}
}
throw 和throws 的区别
- throw 为手动的生成一个异常对象。生成异常对象的过程,声明在方法体内。抛出异常。
- throws 为异常处理的方式。声明在方法的声明处;声明异常。