java异常捕获分析

硅谷探秘者 3427 0 0

java异常捕获分析

    思考问题:

    调用下面的方法分别会返和输出回什么?

package com.itdragon.controller;

import org.junit.Test;

public class TestMain {
	public int test1() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			System.out.println("test1:err");
			a=100;
			return a;
		}finally {
			System.out.println("test1:fin");
			a=200;
			return a;
		}
	}
	public int test2() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			System.out.println("test2:err");
			a=100;
			return a;
		}finally {
			System.out.println("test2:fin");
			a=200;
		}
		return a;
	}
	
	@Test
	public void tests(){
		System.out.println("test1:"+test1());
		System.out.println();
		System.out.println("test2:"+test2());
	}
	
}	

QQ截图20190511202802.png

    众所周知,java捕获到异常时,先执行catch 代码块,如果有finally代码块,那么无论最后有没有异常都会执行finally代码块。

    对于test1都好理解,最后在finally中返回,值为200.

    但是对于test2就有点难以理解,认为应该返回200,但是却返回了100.


    对于上述两个方法简化,在做叙述:

public int test1() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			a=100;
			return a;
		}finally {
			a=200;
			return a;
		}
	}
	public int test2() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			a=100;
			return a;
		}finally {
			a=200;
		}
		return a;
	}

    

反编译出的字节码如下:

test1

public int test1();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: iconst_0	//将int型0推送至栈顶  
         1: istore_1	//将栈顶int型数值存入第二个本地变量  
         2: iconst_1	//将int型1推送至栈顶 
         3: iconst_0	//将int型0推送至栈顶  
         4: idiv		//将栈顶两int型数值相除并将结果压入栈顶  
         5: istore_1	//将栈顶int型数值存入第二个本地变量  
         6: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
         9: istore_1	//将栈顶int型数值存入第二个本地变量  
        10: iload_1		//将第二个int型本地变量推送至栈顶 
        11: ireturn		//从当前方法返回int  
        12: astore_2	//将栈顶引用型数值存入第三个本地变量
        13: bipush        100	//将单字节的常量值(-128~127)推送至栈顶
        15: istore_1	//将栈顶int型数值存入第二个本地变量  
        16: iload_1		//将第二个int型本地变量推送至栈顶 
        17: istore_3	//将栈顶int型数值存入第四个本地变量
        18: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
        21: istore_1	//将栈顶int型数值存入第二个本地变量
        22: iload_1		//将第二个int型本地变量推送至栈顶 
        23: ireturn		//从当前方法返回int  
        24: astore        4		//将栈顶引用型数值存入指定本地变量
        26: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
        29: istore_1	//将栈顶int型数值存入第二个本地变量
        30: iload_1		//将第二个int型本地变量推送至栈顶 
        31: ireturn		//从当前方法返回int  
      Exception table:
         from    to  target type
             2     6    12   Class java/lang/Exception
             2     6    24   any
            12    18    24   any
            24    26    24   any

test2:

 public int test1();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: iconst_0	//将int型0推送至栈顶
         1: istore_1	//将栈顶int型数值存入第二个本地变量	
         2: iconst_1	//将int型1推送至栈顶
         3: iconst_0	//将int型0推送至栈顶
         4: idiv		//将栈顶两int型数值相除并将结果压入栈顶
         5: istore_1	//将栈顶int型数值存入第二个本地变量
         6: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
         9: istore_1	//将栈顶int型数值存入第二个本地变量
        10: goto          34	//无条件跳转
        13: astore_2	////将栈顶引用型数值存入第三个本地变量
        14: bipush        100	//将单字节的常量值(-128~127)推送至栈顶
        16: istore_1	// 将栈顶int型数值存入第二个本地变量
        17: iload_1		//将第二个int型本地变量推送至栈顶
        18: istore_3	//将栈顶int型数值存入第四个本地变量
        19: sipush        200	// 将一个短整型常量值(-32768~32767)推送至栈顶  
        22: istore_1	//将栈顶int型数值存入第二个本地变量 
        23: iload_3		//将第四个int型本地变量推送至栈顶
        24: ireturn		// 从当前方法返回int
        25: astore        4		//将栈顶引用型数值存入指定本地变量
        27: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶  
        30: istore_1	//将栈顶int型数值存入第二个本地变量
        31: aload         4	//将指定的引用类型本地变量推送至栈顶 
        33: athrow		//将栈顶的异常抛出
        34: iload_1		//将第二个int型本地变量推送至栈顶
        35: ireturn		// 从当前方法返回int
      Exception table:
         from    to  target type
             2     6    13   Class java/lang/Exception
             2     6    25   any
            13    19    25   any
            25    27    25   any

        可能对于不是太了解字节码的同学来说不好理解。

        但是从中我的理解是:当有finally块存在的时候,虚拟机执行完catch块中的代码时不会立即返回,而是把return语句给屏蔽了,将catch中的代码执行完以、变量在局部变量表中保存好以后,继续执行finally块中的代码,如果finally块中有返回语句,则直接返回,否则,虚拟机去取在catch块中保存的局部变量,放入栈顶,返回。


猜你喜欢
java基础 1228 Java体系java体系继承图ThrowableThrowable类是所有的父类,见的子类有两个Error、Exception。ErrorError类就是程序运行时候抛出的最严重级别的
official 125 《操作系统》中断机制的诞生早期的计算机各程序只能串行执行,执行完这一个才能执行下一个,所以系统资源利用率低。为了解决上述问题,人们发明了操作系统(作为计算机的管理者),引入中断机制,实现了多道程序并发执行本质:发生中断就意味着需要操作系统介入,开展管理工作。中断的概念和作用1.当中断发生时,CPU立即进入核心态2.当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进行处理3.对于不同的中
spring/springmvc 1155 springmvc统一返回信息当服务器代码为: @RequestMapping("/res") publicMyAjaxResultres(@RequestParam(name
java基础 304 1.HashMap的构造函数1.publicHashMap()publicHashMap(){this.loadFactor=DEFAULT_LOAD_FACTOR;//allotherfieldsdefaulted}构造一个空的HashMap,初始容量为16,负载因子为0.75,负载因子和它的作用将会在下方解释。2.publicHashMap(intinitialCapacity)publicH
java虚拟机(jvm) 3164 Java对象的创建Java是一门面向对象的编程语言,在Java程序运行过程中无时无刻都有对象被创建出来。在语言层面上,创建对象(例如克隆、反序列化)通仅仅是一个new关键字而已,而在虚拟机中,对象
java虚拟机(jvm) 1844 jvm内存模型(1)Java虚拟机在执行Java程序的过程中会把它所管理的内存划为若干个不同的数据区域jvm包括三大子系统:类加载子系统,运行时数据区(内存结构),执行引擎详细图示
java虚拟机(jvm) 2219 jvm内存模型(5)堆内存溢出以及1.模拟堆内存溢出代码packagetest;importjava.util.ArrayList;importjava.util.List
框架 618 参数校验失败统一返回给前端信息参数校验如何使用参考:http://www.jiajiajia.club/blog/artical/yjw520/248校验需要的pom依赖
归档
2018年11月  12 2018年12月  33 2019年01月  28 2019年02月  28 2019年03月  32 2019年04月  27 2019年05月  33 2019年06月  6 2019年07月  12 2019年08月  12 2019年09月  21 2019年10月  8 2019年11月  15 2019年12月  25 2020年01月  9 2020年02月  5 2020年03月  16 2020年04月  4 2020年06月  1 2020年07月  7 2020年08月  13 2020年09月  9 2020年10月  5 2020年12月  3 2021年01月  1 2021年02月  5 2021年03月  7
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo
目录