异常:
声明:
Error类或RuntimeException类的所有异常成为未检查类,其他的为已检查类
声明的都是已检查异常(告诉编译器有这个方法有可能抛出一个异常)(编译器:runtime异常你他妈自己不会改啊?error类我他妈也不会改啊)
会抛出异常的4种情况:
1 调用一个抛出已检查异常的方法
2 运行过程中需要抛出一个已检查异常
(第1种在没有捕获的情况下需要声明(即变成第二种),第2种情况需要声明)
3 程序出现未检查异常
4 java虚拟机和运行时库出现内部错误。
tips
1 子类覆盖的方法,其声明的异常不能比超类中更通用(可以抛出更特定的异常,也可以不抛出异常)
2 抛出的异常有可能是声明的异常的子类。
抛出:
声明的是异常类,抛出的是一个异常对象
1 找到合适的异常类(可以新建自己的异常类)
2 创建这个类的对象
3 将对象抛出
一旦抛出了异常,方法就不会再返回到调用者(如果没有捕获的话),抛出后程序终止执行,并在控制台上打印出异常信息(异常的类型和堆栈的内容)。
捕获:
捕获异常时不需要在方法处声明,在catch语句中声明异常类型的变量,一旦出现catch中声明的异常,将会
1 跳过try剩下的语句;
2 执行catch中的语句。
如果出现catch中没有的异常,则立即退出方法
方法中异常处理的原则(捕获(catch)or抛出(throw)):
捕获那些知道如何处理的异常,传递不知道如何处理的。(如果传递的话必须加上throw声明)
特殊情况下:如覆盖超类的方法,但是超类中的方法没有声明异常,那么必须要捕获异常.
java.lang.Throwable ------>java.lang.Exception------>java.io.IOException
&和&&以及|和||的区别:短的更节省时间
tips:
1 可以用多个catch捕获多个异常,一个catch可以捕获多个异常类型。
2 补货多个异常时隐含为final变量,不能为e赋不同的值。
再次抛出异常与异常链:
1 抛出的已检查异常仍然需要在方法处声明
2 不想知道具体错误细节,但希望知道是否有问题
try{
access the database
}catch(SQLException e){
throw new ServletException("database error" + e.getMessage())//用显示异常信息的构造器
}
3 比第二个更好的方法:异常的包装(initCause(),getCause())
try{
access the database
}catch(SQLException e){
Throwable s = new ServletException();
s.initCause(e);
throw s;
}
得到原始异常:Throwable e = s.getCause(e);
4 如果方法中不能抛出异常(超类中没有声明),则可以在catch中抛出runtime异常(即不用声明)
finally:针对资源回收问题
finally类中的内容,在方法返回调用之前执行
想吧try中的非ioexception异常传给调用者,结果finally中的close()方法中的ioexception异常将他替换了
带资源的try:为了简化
//open a resourse(实现AutoCloseable接口) try{ //work with a resourse } finally{ //close the resourse }
try(Resourse res=...)//解决了同时含有try和close中同时含有的问题,close方法中的异常被抑制
{
//work with res
}
使用异常机制的技巧:
1 异常处理不能代替简单的测试(时间成本太大),只在异常情况下使用异常机制
2 不要过分的细化异常
3 利用异常层次结构
4 不要压制异常
5 在检测错误时,苛刻要比放任好
6不要羞于传递异常