java异常分类和finally代码块中return语句的影响

news2024/9/25 23:11:22

首先看一下java中异常相关类的继承关系:

引用
在这里插入图片描述

1、分类

异常可以分为受查异常和非受查异常,Error和RuntimeException及其所有的子类都是非受查异常,其他的是受查异常。
两者的区别主要在:

  • 受检的异常是由编译器(编译阶段)强制执行的,必须try-catch捕获或者往上抛出,用于指示不受程序控制的异常情况(例如,I/O 错误)。
  • 而非受检的异常在运行时发生,用于指示编程错误(例如,空指针。正因为如此,受检异常在使用的时候需要比非受检异常更多的代码来避免编译错误。

常见的异常有:
在这里插入图片描述
之所以要定义受检异常和非受检异常主要是因为两者有着不同的作用

  • 在程序中,存在一些需要用户在编译期间就去检查的问题,比如FileNotFoundException、IOException,这些异常涉及资源处理,调用者需要捕获,其实它可以提醒开发者,如果被调用的方法出现这类异常时,程序应该做好预判并处理,比如IOExcetion,我们需要对流进行关闭操作。

  • 而非受检发生在运行期间,是程序运行过程中可能发生的错误类型,比如NullpointExcetpion,这些异常我们可以捕获,也可以不捕获。但是捕获这些异常只能打印一些日志,除此之外什么都做不了。(捕获了也无法在程序中解决)

2、finally与return

2.1 finally原理

public class Demo3_11_4 {
  public static void main(String[] args) {
    int i = 0;
    try {
    	i = 10;
    } catch (Exception e) {
    	i = 20;//异常表中有3行,分别是监测try中出现的异常、catch中出现的异常(catch中处理异常时也是可能产生异常的)
    } finally {
    	i = 30;
    }
    System.out.println(i);
  }
}
//输出:30

字节码:
在这里插入图片描述
可以看到在字节码中 finally 中的代码被复制了 3 份,分别放入 try 流程,catch 流程以及 catch 剩余的异常类型流程。当catch中代码出现异常时,该异常对象会被抛出。

2.2 finally 对返回值影响

  1. finally中return
public class Demo3_12_2 {
  public static void main(String[] args) {
    int result = test();
    System.out.println(result);
  }
  public static int test() {
    try {
    	return 10;
    } finally {
    	return 20;
    }
  }
}
//输出 20
  • 字节码
//字节码指令
public static int test();
  descriptor: ()I
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=1, locals=2, args_size=0
      0: bipush 10 // <- 10 放入栈顶
      2: istore_0 // 10 -> slot 0 (从栈顶移除了,后面还有字节码,不能return)
      3: bipush 20 // <- 20 放入栈顶
      5: ireturn // 返回栈顶 int(20)
      6: astore_1 // catch any -> slot 1
      7: bipush 20 // <- 20 放入栈顶
      9: ireturn // 返回栈顶 int(20)
  Exception table:
    from to target type
    0 	 3	 	6		 any
  LineNumberTable: ...
  StackMapTable: ...

由于 finally 中的 ireturn 被插入了所有可能的流程,因此返回结果肯定以 finally 的为准

  1. try中return,finally中修改return值
public class Demo3_12_2 {
  public static void main(String[] args) {
    int result = test();
    System.out.println(result);
  }
  public static int test() {
    int i = 10;
    try {
    	return i;
    } finally {
    	i = 20;
    }
  }
}

//输出10
  • 字节码:
    在这里插入图片描述
    可以看到,在try中执行return时已经暂存的i=10,后续修改i不会改变本地变量表中的i。

2.3 finally中return对异常的影响

在2.1中我们可以看到,为了防止catch捕获异常处理的过程中产生异常后直接抛出而不执行finally中的代码,因此在字节码中,对try中代码也进行了异常的跟踪,并最后抛了出去。

有如下代码:

public class Demo3_12_2 {
  public static void main(String[] args) {
    int result = test();
    System.out.println(result);
  }
  public static int test() {
    int i = 10;
    try {
    	i = 1/0;
    	return i;
    } finally {
    	i = 20;
    	//return i;
    }
  }
}
//输出:30
  • 问题1:会抛出异常吗?
public static int test();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: bipush        10
         2: istore_0
         3: iconst_1
         4: iconst_0
         5: idiv
         6: istore_0
         7: iload_0
         8: istore_1
         9: bipush        20			-----------
        11: istore_0
        12: iload_1
        13: ireturn						-----------
        14: astore_2
        15: bipush        20			-----------
        17: istore_0
        18: aload_2
        19: athrow
      Exception table:
         from    to  target type
             3     9    14   any

从字节码中可以看到,当前代码在try中——字节码3到9(不包括9),出现异常会直接跳到14,将异常对象放到slot2,然后执行finally代码,将20->i,抛出异常对象。所以时可以抛出异常的。

  • 问题2:finally中添加return后会抛出异常吗?
  public static int test();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: bipush        10
         2: istore_0
         3: iconst_1
         4: iconst_0
         5: idiv
         6: istore_0
         7: iload_0
         8: istore_1
         9: bipush        20
        11: istore_0
        12: iload_0
        13: ireturn
        14: astore_2
        15: bipush        20
        17: istore_0
        18: iload_0
        19: ireturn
      Exception table:
         from    to  target type
             3     9    14   any

可以看到,代码finally中添加return后,字节码中 athrow 指令没了,这就表明不会抛出异常了,即finally中的return会吞掉异常对象,所以不要在finally中return。

小结:finally吞掉异常的原因是,要保证finally中代码必须执行,然后才抛出异常,但是如果finally中有return的话,执行到finally中的return方法就结束了,没有机会去跑异常了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CUDA环境搭建(windows10)

CUDA环境搭建[windows10]一、检查显卡支持的cuda版本二、安装vs2019三、安装cuda四、检测cuda是否安装成功五、配置vs项目总结&#xff1a;一、检查显卡支持的cuda版本 &#xff08;1&#xff09;第一种方法&#xff1a;winR打开cmd&#xff0c;输入nvidia-smi&#xff0c;我的…

常用的shell脚步操作

文章目录一、如何开始一个shell脚本?1.基本语法2.变量定义规则二、特色变量1.$n2.$&#xff1f;三、条件判断1&#xff0e;基本语法2.运算符if,for,while四、字符串切割1.从指定位置开始截取从字符串左边开始计数从右边开始计数2.从指定字符&#xff08;子字符串&#xff09;开…

【MySQL】查询操作(基础篇)

目录 1、查询操作(Retrieve) 1.1 全列查询 1.2 指定列查询 1.3 查询字段为表达式 1.4 别名 1.5 去重&#xff1a;DISTINCT 1.6 排序&#xff1a;ORDER BY 1.7 条件查询&#xff1a;WHERE 1.8 分页查询 1、查询操作(Retrieve) 查询操作算的上是 SQL 中最复杂的操作了…

Orcad导出BOM的两种方式比较

两种方法&#xff0c;各有优缺点。推荐使用第二种。一、Capture CIS特有的导BOM方式&#xff0c;用Capture 就没有这个选项点击Stanard,然后可以在左框中select ,add进右边的框&#xff0c;这样导就会导出你想要的属性&#xff0c;同时右下方有个Key选项&#xff0c;你选择outp…

适用于电脑的 5 款免费好用的 PDF 阅读器

PDF 阅读器是任何可以打开PDF 文件的软件&#xff0c;它可能是世界上最知名的文档格式。您可下载的银行对账单、学校的时事通讯——它们可能都是 PDF 格式的。 越来越多的操作系统、智能手机和其他设备包含显示 PDF 文件的内置功能&#xff1b;甚至您的网络浏览器也可能处理它…

Vue2和Vue3响应式的区别

数据响应式是什么&#xff1f; ​所谓 数据响应式 就是建立 响应式数据 与 依赖&#xff08;调用了响应式数据的操作&#xff09;之间的关系&#xff0c;当响应式数据发生变化时&#xff0c;可以通知那些使用了这些响应式数据的依赖操作进行相关更新操作&#xff0c;可以是DOM…

基于ubuntu的STM32嵌入式软件开发(三)——基于官方标准函数库的软件工程移植

本文基于st官方提供的标准库搭建应用软件工程&#xff08;即非cube方式、非寄存器方式&#xff09;&#xff0c;采用标准库搭建的工程具有软件可移植性高、可读性好、符合软件设计人员思维方式。本文描述官方下载标准库及标准库的移植过程&#xff0c;具体流程如下所述&#xf…

不妙,2023年浙大mpa的复试形势比想象的更严峻,又在突突突涨……

都知道浙大MPA项目卷&#xff0c;但都没想到这么卷&#xff01; 很多浙大mpa的考生在一开始的备考初期因为对该项目的认知了解不够清晰从而会导致联考过后功亏一篑。因为是在职类考生群体&#xff0c;因此不少考生会认为以自己的实力和基础应该能够鱼跃龙门榜上有名&#xff0c…

视频会议系统异常中断故障分析案例

1. 背景 某电气化局的用户反馈&#xff0c;近期视频系统在使用过程中出现频繁中断的情况&#xff0c;这种情况影响到用户的视频体验和工作效率。 针对此问题&#xff0c;我们将NetInside流量分析系统部署到电气化局机房&#xff0c;使用流量分析系统提供实时和历史原始流量。…

【Linux】P1 Linux 基础命令(1)

Linux 基础命令&#xff08;1&#xff09;Linux 目录结构Linux 命令ls 展示命令cd 目录切换命令pwd 查看当前工作目录mkdir 创建新的文件夹其他补充知识前言 本节内容&#xff1a;Linux 基本命令&#xff08;1&#xff09;。 下节内容&#xff1a;Linux 基本命令&#xff08;2&…

二进制与十进制转换(包括整数和小数的转换)

二进制与十进制转换&#xff08;包括整数和小数的转换&#xff09; 二进制转十进制 首先要先了解二进制的含义&#xff0c;与十进制相似&#xff0c;二进制代表的是以2的次幂在每一位上的0/1表示&#xff0c;平时我们经常接触的都是整数的二进制&#xff0c;是从2的0次幂开始的…

从WebRtc学习RTP协议

1、TCP为何不适用于实时音视频可靠性是以牺牲实时性为代价的。按照TCP原理&#xff0c;当出现极端网络情况时&#xff0c;理论上每个包的时延可达到秒级以上&#xff0c;而且这种时延是不断叠加的。这对于音视频实时通信来说是不可接受的。TCP为了实现数据传输的可靠性&#xf…

【2223sW2】LOG1

写在前面 好好学习&#xff0c;走出宿舍&#xff0c;走向毕设&#xff01; 一些心路历程记录&#xff0c;很少有代码出现 因为鬼知道哪条代码到时候变成毕设的一部分了咧&#xff0c;还是不要给自己的查重挖坑罢了 23.2.27 文件批量重命名 为了给学姐先整出来一批训练数据&…

Element中树形控件在项目中的实际应用

文章目录1、使用目的2、官网组件3、组合使用组件案例4、在项目中实际应用4.1 组合组件的使用4.1.2 代码落地4.1.3 后台接口数据4.1.4 实际效果官网连接直达&#xff1a;Tree树形控件的使用 1、使用目的 用清晰的层级结构展示信息&#xff0c;可展开或折叠。 2、官网组件 <…

【YoloV5】Deepin系统使用Gpu进行YoloV5训练

Deepin系统使用Gpu进行YoloV5训练&#xff0c;显卡RTX30701.配置环境1.1英伟达的驱动安装2. pytorch安装2.1pytorch环境配置2.2 验证Gpu3.使用Yolo5进行Gpu模型训练3.1 准备需要训练的数据集和标注数据集1.配置环境 1.1英伟达的驱动安装 查看当前自己系统的显卡信息 lspci |…

paddleInfer

一、安装GCC 5.4https://blog.csdn.net/weixin_64064486/article/details/123940266二、安装pycudahttps://blog.csdn.net/zong596568821xp/article/details/86077553/更改的地方是&#xff0c;安装pycuda用的是&#xff1a;pip install pycuda三、安装TensorRT 1、TensorRT下载…

DataGear 制作基于Vue前端框架渲染的数据可视化看板

DataGear 在4.3.0版本新增了dg-dashboard-code特性&#xff0c;并在4.4.0版本进行了改进和增强&#xff0c;结合看板API&#xff0c;可以很方便地制作完全由Vue、React等前端框架渲染的数据可视化看板。 本文基于Vue2、Element UI前端框架的<el-container>、<el-head…

对“车辆销售配置器”的认识与理解

概述 中国汽车市场转为存量阶段后&#xff0c;各车企开始从”以产品为中心“转型到”以客户为中心“&#xff0c;产品的个性化配置需求日益丰富。随着竞争的加剧&#xff0c;车企们不仅要提供出色的产品&#xff0c;而且需要提供更加个性化的产品配置和服务&#xff0c;例如&am…

【Hello Linux】程序地址空间

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍下进程地址空间 程序地址空间程序地址空间语言中的程序地址空间矛盾系统中的程序地址空间为什么要有进程地址空间思维导图总结…

Java经典面试题——String、StringBuffer、StringBuilder有什么区别?

典型回答 String 是Java 语言非常基础和重要的类&#xff0c;提供了构造和管理字符串的各种基本逻辑。它是典型的 Immutable 类&#xff0c;被声明成为 final class &#xff0c;所有属性也都是 final 的。也由于它的不可变性&#xff0c;类似拼接、裁剪字符串等动作&#xff…