今天无意中,同事发现了一个有趣的现象,首先来看一下以下代码:
java 代码会发现,18行加载了一下变量b中的值,所以,其实,在执行代码的第8行时,并不是执行return,而只是往内存中存储变量b的值。
- public class Test {
- private static int todo() {
- int b=1;
- try{
- int a=2/0;
- } catch(Exception e) {
- System.out.println("in catch");
- return 1;
- } finally {
- System.out.println("in final");
- }
- return 2;
- }
-
-
-
- public static void main(String[] args) {
- System.out.println(todo());
-
- }
- }
此时,运行结果为
in catch
in final
1
看到这里,少部分人已经开始不明白了,我们继续看另一则代码(请注意细小的差别):
java 代码
- public class Test {
- private static int todo() {
- int b=1;
- try{
- int a=2/0;
- } catch(Exception e) {
- System.out.println("in catch");
- return b;
- } finally {
- System.out.println("in final");
- }
- return 2;
- }
-
-
-
- public static void main(String[] args) {
- System.out.println(todo());
-
- }
- }
此时,运行结果依旧是
in catch
in final
1
但是通过单步执行,会发现,两种代码的执行顺序有少许差别
第一种代码的try/catch单步执行顺序为
7->10->8
第二种代码的try/catch单步执行顺序为
7->8->10->8
这里我们对其进行了研究,从中间码入手,首先来分别看看两者的中间码:
上述第一块代码的中间码
- 11 ldc <String "in catch"> [22]
- 13 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
- 16 getstatic java.lang.System.out : java.io.PrintStream [16]
- 19 ldc <String "in final"> [30]
- 21 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
- 24 iconst_1
- 25 ireturn
可以发现,明显的执行顺序,1行把装入字符串转入内存,2行打印,4行在把字符串装入内存,5行再打印,7行返回
上述第二块代码的中间码
- 13 ldc <String "in catch"> [22]
- 15 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
- 18 iload_0 [b]
- 19 istore_3
- 20 getstatic java.lang.System.out : java.io.PrintStream [16]
- 23 ldc <String "in final"> [30]
- 25 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
- 28 iload_3
- 29 ireturn
以上的过程,分析下中间码,还是可以理解的,但是非常非常让人奇怪的是,如下的代码(请还是注意不同的细节)
java 代码
- public class Test {
- private static int todo() {
- int b=1;
- try{
- int a=2/0;
- } catch(Exception e) {
- System.out.println("in catch");
- return b;
- } finally {
- b=3;
- System.out.println("in final");
- }
- return 2;
- }
-
-
-
- public static void main(String[] args) {
- System.out.println(todo());
-
- }
- }
此时运行结果照样是
in catch
in final
1
单步执行结果是 7->8->10->11->8
想不通的是,根据单步执行,在finally里对b进行了修改,但是,返回的仍旧是1
再来看看这个代码的中间码:
第三个代码的中间码
- 13 ldc <String "in catch"> [22]
- 15 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
- 18 iload_0 [b]
- 19 istore_3
- 20 iconst_3
- 21 istore_0 [b]
- 22 getstatic java.lang.System.out : java.io.PrintStream [16]
- 25 ldc <String "in final"> [30]
- 27 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
- 30 iload_3
- 31 ireturn
因为,其实我没怎么学过汇编,只是初步的分析了
3行加载b的地址,4行在地址3储存b的值(此时地址3的值为1),5行加载一个常量,6行把常量存入b的地址(此时b的值为3),10行加载地址3的值,最后返回值。
不知道这样的解释是否合理,也请,希望能够得到一个对于try./catch块执行问题的通俗答案,谢谢!
分享到:
- 2007-08-31 20:32
- 浏览 11727
- 评论(1)
- 论坛回复 / 浏览 (1 / 3701)
- 查看更多
相关推荐
总结来说,`try-catch`嵌套在Java中用于更精细化的异常处理,允许我们针对不同类型的异常执行不同的恢复策略。通过这种方式,我们可以编写更健壮、更易维护的代码,确保程序在面对错误时能够优雅地处理并继续运行。
### Java中try-catch的用法详解 #### 一、基本概念 在Java编程语言中,`try-catch`结构是一种用于处理程序运行时可能出现的异常情况的重要机制。通过使用`try-catch`块,开发者可以更加精细地控制程序的行为,并...
`try-catch`块是Java异常处理的核心部分,它允许程序员在代码可能出现问题的地方进行异常捕获和处理,避免程序因未预期的错误而崩溃。下面我们将详细讨论`try-catch`捕获异常的实例。 首先,`try`块是包含可能抛出...
本文将深入探讨Java中的`try-catch-finally`语句块,以及它们在异常处理中的作用。 首先,`try`块是异常处理的起点。在这个代码段中,我们通常会放置可能会抛出异常的代码。当Java执行到可能抛出异常的代码行时,...
总结来说,`try-catch-finally`结构是Java中处理异常的关键工具,它允许开发者优雅地处理错误,保持程序的健壮性,同时确保必要的清理工作得以执行。通过正确使用这些结构,可以提高代码的可读性和可维护性。
"Java中try、catch的使用方法" 本文主要介绍了Java中try、catch的使用方法,通过实例代码详细地介绍了try、catch的使用方法,对大家的学习或工作具有一定的参考借鉴价值。 try-catch语句的语法格式为:try{ //代码...
`try-catch` 结构作为异常处理的核心机制,在各种编程语言中广泛采用,如 Java、C# 和 JavaScript 等。本文将深入探讨 `try-catch` 的基本概念、语法结构及其应用场景。 #### 一、`try-catch` 的基本概念 `try-...
try-catch-finally语句是Java语言中一种常用的异常处理机制,当程序在执行过程中出现异常时,可以使用try-catch-finally语句来捕获和处理异常。下面将详细介绍try-catch-finally语句的使用方法和注意事项。 一、try...
try、catch、finally、return 执行顺序是 Java 编程语言中的一种 exception 处理机制,用于处理程序中的异常情况。下面我们来详细讲解 try、catch、finally、return 执行顺序的规则和特点。 首先,我们需要了解 try...
本示例中的"trycatch.zip"文件内容就是展示了如何在Golang中模拟`try...catch`和`try...catch...finally`。 Golang的核心错误处理方式是通过返回错误值。通常,函数会返回一个错误值,如果在执行过程中遇到问题,就...
`finally`块是可选的,无论`try`和`catch`块中的代码是否抛出异常,`finally`块里的代码都会被执行。这通常用于资源清理,如关闭文件流、网络连接等。即使在`try`或`catch`块中有return语句,`finally`块的代码也会...
根据给定文件的信息,我们可以提炼出关于Java异常处理的关键知识点,特别是如何使用`try`和`catch`来捕获和处理异常。 ### 10.3 使用try和catch捕获异常 #### 10.3.1 try和catch的基础概念 - **try**:尝试执行的...
Java try catch finally异常处理组합是Java语言中的异常处理机制,用于捕获和处理程序中的异常。下面对try catch finally异常处理组合进行详细的介绍。 try catch组合: try catch组合是Java中最基本的异常处理...
当代码执行到try语句块中时,如果出现了异常,Java虚拟机会将其捕获并抛出到catch子句中,在catch子句中可以进行异常处理和错误信息的返回。try catch语句可以捕获到各种类型的异常,包括运行时异常和检查异常。 而...
try块中包含可能会产生异常的代码,当try块内的代码发生异常时,程序会立即跳转到与异常类型相匹配的catch块进行处理。 在catch块中,你可以编写适当的处理逻辑来处理特定类型的异常。每个catch块可以捕获不同类型...
在传统的`try-catch-finally`中,`finally`块用于确保在执行完`try`块后,即使有异常抛出,资源也能被正确关闭。然而,这需要手动调用`close()`方法,如文件流、网络连接等。 Java 7引入的`try-with-resources`语句...
第一:return语句并不是函数的终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂存在栈里面,等待finally执行后再返回) 第二:finally里面不建议放return语句,根据需要,return语句...
在Java中,`try`、`catch`、`finally`和`throw`这四个关键字构成了异常处理的核心。 #### `try`关键字 `try`关键字用于标记一段可能抛出异常的代码块。这部分代码被称为`try`块,它包含了可能会引发异常的操作。...
Java 异常处理 Java 异常处理是 Java 编程语言中的一种错误处理机制,它允许...Java 异常处理是 Java 编程语言中的一种错误处理机制,通过使用 try 块、catch 块和 finally 块,可以捕获和处理运行时的异常情况。
总之,Try…Catch 机制是异常处理的核心,它帮助我们优雅地处理预期之外的问题,保证程序的健壮性。正确地使用 Try…Catch 结构,结合自定义异常和资源管理策略,可以提高代码的稳定性和可维护性。