zoukankan      html  css  js  c++  java
  • try catch finally 执行顺序与抛错机制

    try catch finally 执行顺序与抛错机制

    一、结论

    1. try 先执行 ,若有报错,执行 catch

    2. 不管有没有异常 finally 肯定会执行

    3. try 和 catch 中 存在 return 或者 throwfinally 也会执行

    4. catch 中若报错:

      猜测先 暂存 catch 错误 ,等待 finally 执行完毕后,抛出错误

    5. catch 中若报错, finally 也报错:

      1. 猜测先 暂存 catch 错误 ,等待 finally 执行,发现 finally 存在错误,直接抛出 finally 的错误
      2. 抛出 catch 错误的程序不会执行,所以最终表示为 抛出 finally 错误,catch 错误不显示
    6. 在 try catch 中,如果碰到 return 语句:

      1. 先执行 return 语句表达式 ,但是执行结果会被 局部变量 暂存
      2. 之后执行 finally 内容,再执行 return 操作,返回 局部变量暂存 的结果
    7. try 或 catch 若有 return :

      暂存 return 的执行结果 ,等待 finally 执行完毕后,才返回 try 或 catch 中 return 的执行结果

    8. try 或 catch 若有 return ,finally 也有 return:

      1. 暂存 try 和 catch return 的执行结果 ,等待 finally 执行完毕
      2. finally 存在 return ,直接返回 finally 的 return 值,程序提前退出

    二、场景

    throw 的作用是手动中断程序,抛出一个异常,会被捕获

    以下的 制造一个异常 场景可以视为 throw 一个常量或者其他数据,所以 throw 的场景等同异常场景


    1、无错误情况

    1、正常执行
    2、在 try 中 return 一个 常量
    3、在 try 中 return 一个 常量, 在 finally 中 return 一个 常量
    

    2、有错误情况

    1、在 try 中 制造一个异常
    2、在 try、catch 中 各制造一个异常
    3、在 try、catch、finally 中 各制造一个异常
    
    4、在 try 中 制造一个异常, catch return 一个 常量
    5、在 try 中 制造一个异常, catch return 一个 常量,finally return 一个常量
    

    三、测试代码

    以下测试用例都执行

    console.log(test())
    

    1、正常执行

    let test = function() {
        try {
            console.log('try:>>', 1)
        } catch (e) {
            console.log('catch:>> ', e)
        } finally {
            console.log('finally:>> ')
        }
    }
    // 没有报错,正常输出
    // try:>> 1
    // finally:>> 
    // undefined
    

    2、在 try 中 return 一个 常量

    1. try 中 return 的结果被 局部变量 保存起来,执行 finally 之后再输出
    let test = function() {
        try {
            // 未定义 a
            console.log('try:>>', 1)
            return 2
        } catch (e) {
            console.log('catch:>> ', e)
        } finally {
            console.log('finally:>> ')
        }
    }
    
    // try:>> 1
    // finally:>> 
    // 2
    

    3、在 try 中 return 一个 常量, 在 finally 中 return 一个 常量

    1. try return 的值被 局部变量 保存起来,执行 finally 之后,
    2. 发现 finally 中存在 return ,直接 返回 finally 的 return 结果,程序提前退出
    let test = function() {
        try {
            console.log('try:>>', 1)
            return 2
        } catch (e) {
            console.log('catch:>> ', e)
        } finally {
            console.log('finally:>> ')
            return 3
        }
    }
    
    // try:>> 1
    // finally:>> 
    // 3
    

    4、在 try 中 制造一个异常

    1. try 异常被 catch 捕获,输出 try 异常,继续执行 finally
    let test = function() {
        try {
            console.log('try:>>', a)
        } catch (e) {
            console.log('catch:>> ', e)
        } finally {
            console.log('finally:>> ')
        }
    }
    // catch:>>  ReferenceError: a is not defined
    // finally:>> 
    // undefined
    

    5、在 try、catch 中 各制造一个异常

    1. try 异常被 catch 捕获,此时catch 异常,猜测先 暂存 catch 错误 ,等待 finally 执行完毕后,抛出 catch 错误
    let test = function() {
        try {
            console.log('try:>>', a)
        } catch (e) {
            console.log('catch:>> ', e)
            console.log('catch:>> ', b)
        } finally {
            console.log('finally:>> ')
        }
    }
    
    // catch:>>  ReferenceError: a is not defined
    // finally:>> 
    // ReferenceError: b is not defined
    

    6、在 try、catch、finally 中 各制造一个异常

    1. try 异常被 catch 捕获,此时 catch 异常,猜测先 暂存 catch 错误 ,等待 finally 执行,发现 finally 存在错误,直接抛出 finally 的错误
    2. 抛出 catch 错误的程序不会执行,所以最终表示为 抛出 finally 错误,catch 错误不显示
    let test = function() {
        try {
            console.log('try:>>', a)
        } catch (e) {
            console.log('catch:>> ', e)
            console.log('catch:>> ', b)
        } finally {
            console.log('finally:>> ')
            console.log('finally:>> ', c)
        }
    }
    
    // catch:>>  ReferenceError: a is not defined
    // finally:>> 
    // ReferenceError: c is not defined
    
    

    7、在 try 中 制造一个异常, catch return 一个 常量

    1. try 异常被 catch 捕获, 局部变量暂存 catch return 的执行结果
    2. 执行 finally 之后,返回 局部变量暂存的结果
    let test = function() {
        try {
            console.log('try:>>', a)
        } catch (e) {
            console.log('catch:>> ', e)
            return 1
        } finally {
            console.log('finally:>> ')
        }
    }
    
    // catch:>>  ReferenceError: a is not defined
    // finally:>> 
    // 1
    
    

    8、在 try 中 制造一个异常, catch return 一个 常量,finally return 一个常量

    1. try 异常被 catch 捕获, 局部变量暂存 catch return 的执行结果 ,等待 finally 执行完毕
    2. finally 存在 return ,直接返回 finally 的 return 值,程序提前退出
    let test = function() {
        try {
            console.log('try:>>', a)
        } catch (e) {
            console.log('catch:>> ', e)
            return 1
        } finally {
            console.log('finally:>> ')
            return 2
        }
    }
    
    // catch:>>  ReferenceError: a is not defined
    // finally:>> 
    // 2
    

    9、验证 try return 后,结果暂存,执行 finally 后,最后返回暂存结果

    let test = function() {
        let x = 1
        try {
            // 此处 执行 ++x 表达式, x = 2,但是程序不会直接返回结果
            // 而是会使用 局部变量 缓存 return 的值 2 
            // 等待 finally 执行完成后,再 return 缓存的 局部变量值
            return ++x
        } catch (e) {
            
        } finally {
            // 这里 x = 3
            // x 变成了 3,但是最终函数执行的返回值是 2
            ++x
        }
        // 因为上面 return ,此处不执行
        console.log('x :>> ', x);
        return x
    }
    // 最后输出结果为: 2
    // 分析:
    // 1、
    // try 执行 ++x 表达式, x = 2,但是程序不会直接返回结果
    // 而是会使用 局部变量 缓存 return 的值 2 
    
    // 2、
    // 执行 finally
    // x = 3
    
    // 3、
    // finally 执行完成后, return 缓存的 局部变量值 2
    // 最后输出结果为 2
    
  • 相关阅读:
    javaweb请求编码 url编码 响应编码 乱码问题 post编码 get请求编码 中文乱码问题 GET POST参数乱码问题 url乱码问题 get post请求乱码 字符编码
    windows查看端口占用 windows端口占用 查找端口占用程序 强制结束端口占用 查看某个端口被占用的解决方法 如何查看Windows下端口占用情况
    javaWeb项目中的路径格式 请求url地址 客户端路径 服务端路径 url-pattern 路径 获取资源路径 地址 url
    ServletRequest HttpServletRequest 请求方法 获取请求参数 请求转发 请求包含 请求转发与重定向区别 获取请求头字段
    HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码
    Servlet主要相关类核心类 容器调用的过程浅析 servlet解读 怎么调用 Servlet是什么 工作机制
    linq查询语句转mongodb
    winddows rabbitmq安装与配置
    Redis For Windows安装及密码
    出现,视图必须派生自 WebViewPage 或 WebViewPage错误解决方法
  • 原文地址:https://www.cnblogs.com/linjunfu/p/12850555.html
Copyright © 2011-2022 走看看