zoukankan      html  css  js  c++  java
  • Java笔记(三)异常

    异常

    一、概念

    一)为什么会有Java异常机制

    在没有Java异常机制的情况下,唯一的退出机制就是返回值,判断是否异常的方法就是

    返回值。方法根据是否异常返回不同的返回值,调用者根据不同的返回值进行判断。每一

    层方法都需要对调用的方法的不同返回值进行检查和处理,程序的正常逻辑和异常逻辑混杂

    到一起,使代码难以阅读和维护。另外,异常毕竟是少数,程序员因此常常偷懒,忽略对异常

    返回值的检查,降低了程序的可靠性。

    在有了异常机制后,程序的正常逻辑与异常逻辑就可以分离,异常情况就可以集中处理,异常还可以

    自动向上传递,不再需要每层方法都进行处理,异常可不可能被自动忽略,从而处理异常的代码大大

    减少,代码的可读性,可维护性,可靠性都得到了提高。

    二)Java异常处理机制

    Java异常的默认处理机制:打印异常栈到屏幕,并退出程序。

    异常处理机制会从当前函数查找谁捕获了该异常,如果这一层函数没有捕获就依次向

    上一层函数查找,直到主函数,如果主函数也没有捕获该异常,就使用默认机制,打印

    异常栈信息,并退出程序。

    异常是相对于return的一种退出程序的机制可以由throw语句触发,也可以由系统触发。

    三)异常的分类

    异常可以分类为:

    1)受检(checked)异常:强制要求程序员处理(捕获或者通过throws关键字声明)的异常,否则编译器会报错。

    2)未受检(unchecked)异常:不要求程序员处理。

    关于受检异常和未受检异常,以前的说法是:

    未受检异常属于编程的逻辑错误,编程时应该检查以避免这些错误,比如空指针异常,

    如果真的出现这种错误,程序退出也是正常的,程序员应该检查代码BUG而不是想办法

    处理这种异常。受检异常表示程序本身没问题,但由于I/O、网络、数据库等不可预测的

    错误导致的异常,调用者应该处理。

    但实际上编程错误也是应该处理的,尤其Java被广泛应用于服务器应用中,不能

    因为一个逻辑错误就使程序退出。所以,目前一种更被认同的的观点是:Java中

    对受检异常和未受检异常的区分是没有太大意义的,可以统一使用未受检异常来代替。

    这种观点的基本理由是:无论受检异常还是未受检异常,无论是否出现在throws声明中

    ,都应该在合适的地方以适当的方式进行处理,而不只是为了满足编译器的要求盲目处理

    异常,既然都要进行处理异常,受检异常的强制声明和处理就显得很繁琐,尤其在调用层次比较深的情况下。

    异常的类体系:

    1.Throwable

    有四个构造方法:

    1. public Throwable()
    2. public Throwable(String message)
    3. public Throwable(String message, Throwable cause)
    4. public Throwable(Throwable cause)

    其中message表示异常消息,cause表示触发该异常的其他异常。异常可以形成一个异常链,

    上层的异常由底层触发,cause表示的是底层异常。Throwable还有一个public方法用于设置cause:

    Throwable initCause(Throwable cause)

    Throwable某些子类没有构造函数就可以通过该方法设置。这个方法最多只能被调用一次。

    2.Error

    Error(unchecked):描述了Java运行时系统内部错误和资源耗尽错误。

    应用程序不应该抛出此类异常。如果出现这样的内部错误,应该通报给客户,并尽力使程序安全退出。

    3.Exception

    Exception层次:

    RuntimeException(unchecked):由于程序错误(代码有问题)导致的异常,如

    错误的类型转换,

    数组访问越界,

    访问空指针

    这类异常一定是你的错误。

    其他异常(checked):程序本身没有问题,由于像I/O错误这类问题导致的异常。如:

    试图在文件末尾后面读取数据

    试图打开一个不存在的文件。

    编译器将核查是否所有checked异常提供了异常处理器。

    四)异常的处理

    重新抛出:因为当前层级不能处理该异常,抛出给调用者处理。

    抛出一个新异常:当前异常所包含的信息不够,或者太过详细。

    throws关键字:用于声明一个方法可能抛出的异常,这个声明的

    含义是这个方法可能抛出这些异常,并且没有对这些异常进行处理,调用者必须进行处理。

    finally执行细节:

    1)如果在try或者catch语句内有return语句,则return语句在finally语句

    执行结束后才执行,但finally并不能改变返回值。

        //返回0
        public static int test(){
            int ret = 0;
            try{return ret;
            }finally{
                ret = 2;
            }
        }

    2)如果在finally语句中也有return语句:try和catch中的return会丢失,实际返回finally中的返回值。

    finally中有return还会掩盖try和catch内的异常,就像没有异常发生一样。如果finally中抛出了异常,

    则原异常也会被覆盖。

        public static int test(){
            int ret = 0;
            try{
                int a = 5/0;
                return ret;
            }finally{
                //返回2而不向上传递异常
                return 2;
            }
        }
        public static void test(){
            try{
                int a = 5/0;
            }finally{
                //原来异常ArithmeticException丢失
                throw new RuntimeException("hello");
            }
        }

    因此:应该避免在finally中return或者抛出异常,如果调用的其他代码可能抛出异常,

    则应该捕获异常并进行处理。

    Simple is important!
  • 相关阅读:
    【linux】系统初始化的shell脚本
    【mysql】数据库Schema的优化
    【mysql】使用xtrabackup在线增量备份及恢复数据库
    mysql中日志的配置与分析
    Javascript 计算字符串所占字节数
    Javascript调试利器console的使用
    Javascript中类型的判断
    Javascript中的数据类型知多少
    Javascript中bind()方法的使用与实现
    【mysql】Innodb三大特性之insert buffer
  • 原文地址:https://www.cnblogs.com/Shadowplay/p/9946536.html
Copyright © 2011-2022 走看看