Java中的异常体系小结

今天来说一说Java的异常与捕获,首先了解一下什么叫异常体系。
异常体系:就是当程序出现错误时,能够最大化减少损失的一种手段。
在Java中异常也是类。
(1) 关于异常的继承关系如下图:
在这里插入图片描述
这里注意:只有Throwable以及其子类能够进行异常捕获与处理。
下面再来说一说这几种异常的不同:
Error:描述JVM(Java虚拟机)运行时内部错误,如堆栈溢出的错误。
Exception:这种错误是程序中普遍存在的,由于代码问题产生的错误。
IOException:继承自Exception,用于输入输出产生的异常,比如在程序中打开了一个并不存在的文件。
RuntimeException:发生在运行时异常,如数组越界异常,类型转换异常,空指针异常(NPE)
所有这些异常又可分为受查异常和非受查异常。

非受查异常: Error,RuntimeException及其子类属于非受查异常,不强制用户进行异常处理。
受查异常: 除了非受查异常的所有异常都属于受查异常,会强制用户进行异常处理。
异常处理:当异常产生时,尽量保证异常之后的代码能够正常执行。
(2) 异常的处理
格式:try{
}
[catch…]
[catch…]

[finally]

★第一种: try…[1~n] catch… (catch可有多个,try只有一个)
★第二种:try…finally…
★第三种:try…[1~N]catch…finally

那么,try,catch,finally每一部分都有什么作用呢?
try: 所有可能出现的异常的代码
catch: 当相应异常出现时,捕获该异常,然后自定义处理方式
finally: 保证重点代码(如IO流的关闭,JDBC资源的释放等)一定会被执行的机制,
注意!!!无论是否产生异常,finally代码块中的内容一定会被执行。
首先来看一段代码

public class Test0 {
    public static void main(String[] args){
        System.out.println("1,计算开始前...");
        try{
            System.out.println("2,计算开始..."+(10/0));
        }catch(ArithmeticException e){
            System.out.println("3,异常被处理");
        }
        System.out.println("4,运算结束");
    }
}

看打印输出结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\lib\idea_rt.jar=24918:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\code\java\Base\target\classes" TryCatch.Test0
1,计算开始前...
3,异常被处理
4,运算结束

Process finished with exit code 0

因为有了try…catch语句,所以保证了运算在出现错误,的情况下,后面的代码依然能正常运行,这就是异常处理的作用。
再来看一段比较有意思的代码:猜猜它会输出什么???

public class Test0 {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test() {
        try {
            System.out.println(10 / 0);
            return 0;
        } catch (ArithmeticException e) {
            return 1;
        } finally {
            return 2;
        }
    }
}

首先按照我们一般的思维逻辑想一想,当主方法调用test()函数进入try语句块后,因为除数不能为0的缘故,所以放弃执行try语句块,转而去执行catch块去抛出异常然后返回1,但真的是这样吗?来看一下程序运行结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\lib\idea_rt.jar=25093:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\code\java\Base\target\classes" TryCatch.Test0
2

Process finished with exit code 0

输出的是2,这一正好印证了我们上面的那句话:无论是否产生异常,finally代码块中的内容一定会被执行。
那么,是不是绝对的呢?这里要说一个特殊情况,唯一除了一下代码:System.exit();
此方法是终止当前虚拟机的运行,也就是强制性地退出程序。这样一来,若在finally语句块前调用了此方法,finally语句块当然不会执行了。
eg:

public class Test0 {
    public static void main(String[] args){
        try {
            System.out.println("1");
            //系统退出
            System.exit(0);
        } catch (ArithmeticException e) {
            System.out.println("2");
        } finally {
            System.out.println("3");
        }
    }
}

输出结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\lib\idea_rt.jar=25149:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\code\java\Base\target\classes" TryCatch.Test0
1

Process finished with exit code 0

下面再来简单总结一下throws和throw的区别:
throws: 用在方法声明上,明确表示该方法可能会产生异常,当异常产生时,将异常对象仍回给调用者。
throw: 用在方法中,表示人为进行异常对象的产生。一般与自定义异常类搭配使用。
eg: throws的使用

public class Test1 {
    public static void main(String[] args){
        System.out.println(Caculate(10,0));
    }
    public static int Caculate(int a,int b)throws ArithmeticException{
        return a/b;
    }
}

输出显示:

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at TryCatch.Test1.Caculate(Test1.java:8)
	at TryCatch.Test1.main(Test1.java:5)

Process finished with exit code 1

可以看出Caculate在方法声明时用throw明确表示该方法可能会产生异常,因此当主方法调用该方法时,将异常对象扔给了主方法,让主方法来替它背着个锅。

eg: throw的使用

public class Test1 {
    public static void main(String[] args){
        test();
    }
    public static void test(){
        throw new RuntimeException("这个异常很有趣!!!");
    }
}

输出显示如下:

Exception in thread "main" java.lang.RuntimeException: 这个异常很有趣!!!
	at TryCatch.Test1.test(Test1.java:8)
	at TryCatch.Test1.main(Test1.java:5)

Process finished with exit code 1

可见:throw可以人为地产生异常对象。
再来看看两段代码,体会一下throw的存在意义:

// 代码1:(没有throw)
public static void main(String[] args) {
       try{
            System.out.println(10/0);
            
       } catch(Exception e){
           System.out.print(1);
       }
       finally{
           System.out.print(2);
       }
       System.out.println(3);
    }
}
//代码2:(有throw)
public static void main(String[] args) {
       try{
            System.out.println(10/0);
            
       } catch(Exception e){
           System.out.print(1);
           throw new RuntimeException();
       }
       finally{
           System.out.print(2);
       }
       System.out.println(3);
    }
}

猜猜它们分别会输出什么?

//代码1的结果
"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\lib\idea_rt.jar=11311:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\code\java\Base\target\classes" TryCatch.WhereFirst
123

Process finished with exit code 0
//代码2的结果
"C:\Program Files\Java\jdk1.8.0_131\bin\java" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\lib\idea_rt.jar=12142:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;D:\code\java\Base\target\classes" TryCatch.WhereFirst
12
Exception in thread "main" java.lang.RuntimeException
	at TryCatch.WhereFirst.main(WhereFirst.java:10)

Process finished with exit code 1

可见,加了throw之后,异常处理外的代码将不再执行。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值