• No.8 异常捕捉的陷阱


    1. 正确关闭资源

    • 开发中打开的一些物理资源,必须显示进行关闭。Java回收机制是内存管理的一部分,只能对堆内存回收,对程序中打开的物理资源无能为力。必须进行显式关闭资源

    2. finally

    • 不论try块是正常结束,还是中途非正常退出,即使其包含return语句,finally块都会执行
    • 但是碰到System.exit(0)时呢?System.exit(0)将停止当前线程和所有其他当场死亡的线程。finally块不能使已经停止的线程继续执行,因此,其中的方法就得不到执行
    • 那么遇到System.exit(0)应该怎么关闭资源呢?
      • 注册关闭钩子,因为System.exit(0)被调用时,虚拟机退出前要执行清理工作:执行系统中注册的所有关闭钩子
        public class ExitHook {
            public static void main(String[] args) throws IOException {
                final FileOutputStream fos;
                fos = new FileOutputStream("a.bin");
                System.out.println("打开物理资源");
                
                Runtime.getRuntime().addShutdownHook(new Thread(){
                    public void run() {
                        if (fos != null) {
                            try {
                                fos.close();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        System.out.println("关闭了物理资源");
                    }
                });
                
                // 退出程序
                System.exit(0);
                
            }
        }
        View Code

         关闭钩子负责在程序退出时回收系统的资源

    • 只要Java虚拟机不退出,不管try块正常结束,还是遇到异常非正常退出,finally块总会获得执行机会
      • 当Java程序try、catch块中遇到了return语句时,并不会立即执行该语句,而是:去寻找异常处理流程中是否包含finally块,若无,方法执行return结束;若有,开始执行finally块,当finally块执行完后,调回去执行return语句结束,如果finally块中含有return语句,则直接在finally块中结束方法,不会再跳回去执行try块中的return语句
      • 当Java程序try、catch块中遇到了throw语句时,并不会立即执行该语句,抛出异常,而是:去寻找异常处理流程中是否包含finally块,若无,方法执行throw抛出异常;若有,开始执行finally块,当finally块执行完后,调回去执行throw抛出异常,如果finally块中含有return语句,则直接在finally块中结束方法,不会再跳回去执行try块中的throw抛出异常

    3. catch块

    • 对Java的异常捕捉,每个try至少  需要 一个 catch或者finally块
    • 异常捕获时,先捕获小异常,再捕获大异常
    • 不要用异常来进行流程控制:难以阅读、运行速度慢。异常是为捕获异常而存在的,不能用其进行流程控制
    • 只可以捕获可能抛出的异常
      • 可以在任意想捕获异常的地方捕获RuntimeException异常、Exception异常,但是对于其他checked异常(Exception异常是个另类),只有当可能抛出该类异常时才能 捕获,否则编译错误
    • 实际修复
      • 方法知道怎么修复异常,try...catch
      • 方法不知道怎么修复,抛出
        • 在catch块中不进行修复又调用抛出异常的该方法,造成无线递归,StackOverflowError
        • 无论如何不要在finally块中调用可能引起异常的方法,这将导致该方法的异常不能被正常抛出,甚至StackOverflowError错误也不能终止程序,只能采用强行结束进程

    4.继承得到的异常

    • 子类重写父类父类的方法,不能声明抛出比父类类型更多、范围更大的异常。也就是说只能抛出其子类、相同的、或者不抛出
    • 实现接口中的方法时抛出异常要求同上。当是实现多个接口时,多个接口若有相同的方法,在实现该方法时,抛出的异常只能是多个接口分别可以抛出的异常类型的交集,即必须满足每个接口的要求。(方法不抛出异常,肯定是其的一个交集)
    PS:不足之处,欢迎指正、交流
  • 相关阅读:
    Java Socket通信实现私聊、群聊
    一套简单的web即时通讯——第二版
    一套简单的web即时通讯——第一版
    前后端API交互数据加密——AES与RSA混合加密完整实例
    跨境电商ERP中的自动化 3.平台订单自动发货
    跨境电商ERP中的自动化 2.平台商品和本地单品自动绑定
    跨境电商ERP中的自动化 1.平台订单自动同步至本地
    小特工具箱3.0版发布 春节优惠价99元/套
    河南农信移动支付解析
    win10 chrome 百分浏览器 centbrowser 收藏夹栏字体突然变小
  • 原文地址:https://www.cnblogs.com/fang--/p/6272866.html
Copyright © 2020-2023  润新知