异常
简介
异常类都继承于Throwable; 两个大子类Error, Exception
Error:指系统错误,比如说内存溢出、虚拟机异常等
Exception:编码、环境、用户操作输入出现问题
- RuntimeException 非检查异常 ,引起原因:比如引用了一个空对象的属性或方法;数组访问越界;错误类型转换;整除0
- 运行时异常,由JVM自动抛出,自动捕获
异常情况 | 对应的异常 | |
引用了一个空对象的属性或方法 | NullPointerException空指针异常 | String str=null; System.out.println(str.length()); |
数组访问越界 | ArrayIndexOutOfBoundsException数组下标越界异常 | |
类型转换异常 | ClassCastException | |
算数异常 | ArithmeticException |
- 其他异常被称为检查异常;需要手动添加捕获和处理语句。
文件异常 | IOException | 文件找不到了 |
SQL异常 | SQLException | 连接错误 |
输入不匹配异常 | InputMismatchException |
try-catch-finally
使用try-catch或try-catch-finally的语句块来处理异常。
try{
//一些会抛出异常的方法
}catch(Exception e){
//处理该异常的代码块
}catch(Exception e){
//处理该异常的代码块
}...(n个catch块)...{
}finally{
//最终将要执行的一些代码
}
e.printStackTrace(); //打印异常的具体信息
注意事项
- 顺序问题:先小后大,即先子类后父类的顺序写catch语句块(抛出异常时,异常处理系统会就近寻找匹配的异常处理程序)
异常抛出
throws
写在方法名和方法参数表之后,在方法体之前,用它修饰的方法向调用者表明该方法可能会抛出某种/多种类型的异常。
public void 方法名(参数列表)throws 异常列表{
//调用会抛出异常的方法或者抛出一个新异常: throw new Exception();
}
public void test1() throws DrunkExeption {
throw new DrunkExeption(" don't drink when drive");
}
throw
将产生的异常抛出(动作)。
- 如果某个方法调用到了会抛出异常的方法,那么必须添加try...catch语句去尝试捕获这种异常,或者添加throws声明,将异常抛出给更上一层的调用者去处理。
//抛出异常的方法
public void divide(int one, int two) throws Exception{
if(two==0)
throw new Exception("除数不能为0");
else
System.out.println(one/two);
}
//调用抛出异常的方法,用try..catch捕获
public void compute() {
//...
try {
divide(5,0);
}catch(Exception e){
System.out.println(e.getMessage());
}
}
//不能处理异常,则继续声明抛出该异常,由更上一层的调用者处理
public void compute2() throws Exception{
//...
divide(5,0);
}
自定义异常
class 自定义异常类 extends 异常类型{
}
//必须继承于Java标准类库中意思相近的异常类型或Exeption类
public class DrunkExeption extends Exception{
public DrunkExeption() {
}
public DrunkExeption(String message) {
super(message);
}
}
异常链
把捕获的异常包装成一个新的异常,在新的异常里添加对原始异常的引用,再把这个新异常抛出,它们就像是链式反应一样,一个导致另一个,这种情况就叫异常链。
public class ChainTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ChainTest ct=new ChainTest();
try {
ct.test2();
}catch(Exception e) {
e.printStackTrace();
}
}
public void test1() throws DrunkExeption {
throw new DrunkExeption(" don't drink when drive");
}
public void test2() {
try {
test1();
//在catch块中把捕获的DrunkExeption包装成一个新的运行时异常,抛出
}catch(DrunkExeption e) {
RuntimeException newExc=new RuntimeException("创建一个runtime exception");
newExc.initCause(e);//引用原始异常
throw newExc;//抛出新异常
}
}
//更简便的写法
public void test2() {
try {
test1();
}catch(DrunkExeption e) {
RuntimeException newExc=new RuntimeException(e);
throw newExc;//抛出新异常
}
}
}
实际应用中的经验与总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch来处理
- 在多重catch块后面,可以加一个catch(Exception )来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切记仅简单调用printStackTrace()去打印输出
- 尽量添加finally语句块去释放占用的资源,尤其是有网络连接和连接数据库的情况