异常机制(Exception)
异常的定义:指程序运行中出现的不期而至的各种状况
-
java中所有错误的超类为:Throwable。其下有两个子类:Error和Exception
-
Error的子类描述的都是系统错误,比如虚拟机内存溢出等。
-
Exception的子类描述的都是程序错误,比如空指针,下表越界等。
-
通常我们程序中处理的异常都是Exception。
异常处理机制中的try-catch
异常处理机制中的try-catch
-
语法:
try{代码片段…}catch(XXXException e){出现错误后的补救措施(B计划)}
-
try{}语句块不能单独写,后面要么跟catch语句块要么跟finally语句块,异常处理机制关注的是:明知道程序可能出现某种错误,但是该错误无法通过修改逻辑完全规避掉时,我们会使用异常处理机制,在出现该错误是提供一种补救办法。凡是能通过逻辑避免的错误都属于bug!就应当通过逻辑去避免!
-
捕获异常的方式
//这里只是举例异常,实际操作中空指针是需要修复的,属于bug System.out.println("程序开始了"); String line= null; System.out.println(line.length()); System.out.println("程序结束了"); //创建一个空指针异常,执行后会显示空指针异常NullPointerException,未抛出或执行操作的话会直接结束程序。不会执行最后一句输出语句 //使用trycatch进行操作,程序不会报错,并且会捕获异常并正常执行至最后 System.out.println("程序开始了"); try{ String line= null; System.out.println(line.length()); }catch (NullPointerException e){ System.out.println("空指针异常"); } System.out.println("程序结束了"); //异常如果没有进行及时捕捉,仍会报错,而catch是可以写多个的,所以可以多次进行异常捕获 System.out.println("程序开始了"); try{ String line= ""; System.out.println(line.length()); System.out.println(line.charAt(0));//返回字符串当前位置上的得字符 }catch (NullPointerException e){ System.out.println("空指针异常"); }catch (StringIndexOutOfBoundsException e){//如果没有则会出现异常字符串下标越界 System.out.println("字符串下标越界异常"); } System.out.println("程序结束了"); //现在的异常机制是可以同是处理多个异常的,如果两个异常可以用给同一个解决办法,可以合并异常 System.out.println("程序开始了"); try{ String line= ""; System.out.println(line.length()); System.out.println(line.charAt(0));//返回字符串当前位置上的得字符 }catch (NullPointerException|StringIndexOutOfBoundsException e){ System.out.println("空指针异常或字符串下标越界异常"); } System.out.println("程序结束了"); //因为工作中不一定会囊括所有的错误,所以一般可以在最后设置一个总的异常捕捉,用来进行相关操作 System.out.println("程序开始了"); try{ String line= "abc"; System.out.println(line.length()); System.out.println(line.charAt(0));//返回字符串当前位置上的得字符 System.out.println(Integer.parseInt(line));//将字符串转为int值 }catch (NullPointerException|StringIndexOutOfBoundsException e){ System.out.println("空指针异常或字符串下标越界异常"); }catch (Exception e){ System.out.println("发生未知错误,请联系相关人员"); } System.out.println("程序结束了");
注意:当try语句块中语句发生错误后,发生错误语句下面的代码将不会执行,同时catch其中一个捕获异常后,后面的捕获异常(finally语句的代码除外)也将不会在继续执行。
异常处理机制中的finally
-
finally块定义在异常处理机制中的最后一块。它可以直接跟在try之后,或者最后一个catch之后。
-
finally可以保证只要程序执行到了try语句块中,无论try语句块中的代码是否出现异常,最终finally都必定执行。
-
finally通常用来做释放资源这类操作,比如IO操作后的关闭流动作就非常适合在finally中进行
System.out.println("程序开始了"); try{ String line= "abc"; System.out.println(line.length()); System.out.println(line.charAt(0));//返回字符串当前位置上的得字符 return; System.out.println(Integer.parseInt(line));//将字符串转为int值 }catch (Exception e){ System.out.println("发生未知错误,请联系相关人员"); }finally { System.out.println("finally代码执行了"); } System.out.println("程序结束了");
IO操作时的异常处理机制应用
//在实际操作中需要充分考虑到各种情况,及时对问题进行处理
FileOutputStream fos = null;
try {
fos = new FileOutputStream("fos.dat");
fos.write(1);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fos!=null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
自动关闭特性
- JDK7之后,java提供了一个新的特性:自动关闭。旨在IO操作中可以更简洁的使用异常处理机制完成最后的close操作。
- 语法:try(定义需要在finally中调用close()方法关闭的对象.){IO操作}catch(XXXException e){ …}
- 这样代码是编译器认可的,而不是虚拟机。编译器在编译代码后会在编译后的class文件中改回成上面案例的代码样子。
FileOutputStream fos = null;
try (
FileOutputStream fos = new FileOu tputStream("fos.dat")
){
fos.write(1);
} catch (IOException e) {
e.printStackTrace();
}
throw关键字
throw用来对外主动抛出一个异常,通常下面两种情况我们主动对外抛出异常:
-
1:当程序遇到一个满足语法,但是不满足业务要求时,可以抛出一个异常告知调用者。
-
2:程序执行遇到一个异常,但是该异常不应当在当前代码片段被解决时可以抛出给调用者。
//throw抛出异常后,后面的代码就不会继续执行 //新建测试类Person,里面有sage年龄属性和get/set方法 Person p = new Person(); p.setSage(200);//赋值年龄200,满足语法,但是不满足业务 System.out.println("此人的年龄"+p.getSage());
throws关键字
注意,永远不应当在main方法上使用throws!!
当一个方法中使用throw抛出一个非RuntimeException的异常时,就要在该方法上使用throws声明这个异常的抛出。此时调用该方法的代码就必须处理这个异常,否则编译不通过。
//在测试类中修改set方法,进行异常机制抛出
public void setSage(int sage) throws Exception{
if (sage<0||sage>150){
throw new Exception("年龄不合法");
}
this.sage = sage;
}
当我们调用一个含有throws声明异常抛出的方法时,编译器要求我们必须处理这个异常,否则编译不通过。 处理手段有两种:
-
使用try-catch捕获并处理这个异常
-
在当前方法(本案例就是main方法)上继续使用throws声明该异常的抛出给调用者解决。 具体选取那种取决于异常处理的责任问题。
//使用trycatch Person p = new Person(); try { p.setSage(200);//赋值年龄200,满足语法,但是不满足业务 } catch (Exception e) { e.printStackTrace(); } System.out.println("此人的年龄"+p.getSage());
含有throws的方法被子类重写时的规则
public class ThrowsDemo {
public void dosome()throws IOException, AWTException {}
}
class SubClass extends ThrowsDemo{
// public void dosome()throws IOException, AWTException {}
//允许仅抛出部分异常
// public void dosome()throws IOException {}
//允许不再抛出任何异常
// public void dosome(){}
//允许抛出超类方法抛出异常的子类型异常
// public void dosome()throws FileNotFoundException {}
//不允许抛出额外异常
// public void dosome()throws SQLException {}
//不允许抛出超类方法抛出异常的超类型异常
// public void dosome()throws Exception{}
}