六个例子彻底理解finally语句块

六个例子彻底理解finally语句块

这篇博客主要弄清楚两个问题

   1. finally块中的代码是否一定会执行

   2. finally块中的代码什么时候被执行

首先开始第一个:

finally块中的代码一定会被执行么?

答案是否定的,主要有以下几种情况:

  1.try之前发生异常或者直接结束的情况.

  finally是与try , catch配套使用的,finally生效的最大的前提就是得能进行到try语句内,例如以下这种情况就属于没有进入到try然后finally不执行的情况:

        int i = 5 / 0;
        try {
            System.out.println("Try block");
        } catch (Exception e) {
            System.out.println("Catch block");
        }finally {
            System.out.println("Finally block");
        }

  2.try语句内强制退出程序

  比较好理解,如下:

        try {
            System.out.println("Try block");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("Catch block");
        }finally {
            System.out.println("Finally block");
        }

        //输出
        Try block

finally是什么时候执行的?

先看实例:以下程序的输出结果是什么?

public static int test() {
        try {
            return 1;
        } catch (Exception e) {
            return 0;
        } finally {
            System.out.println("Finally block");
        }
    }

    public static void main(String[] args) {
        System.out.println(FinallyTest.test());
    }
结果:
Finally block
1

为何会出现这种情况?

Java语言的异常处理中,finally的作用就是为了保证无论出现什么情况,finally里面的代码一定会执行(当然并不能满足所有的情况).

由于程序执行return就意味着结束对当前函数的调用并且跳出这个函数,因此所有的必须要执行的语句都应该在return之前执行(除非遇到exit函数).因此finally块中的函数也是要在return之前执行的.

如下图:

这里写图片描述

至于进行的什么处理下文再说

再看一个实例:
public static int test() {
        try {
            return 1;
        } catch (Exception e) {
            return 0;
        } finally {
            System.out.println("Finally block");
            return 3;
        }
    }

    public static void main(String[] args) {
        System.out.println(FinallyTest.test());
    }

结果:

Finally block
3

这个实例说明如果finally块内也包含return语句,那么finally内的return语句会覆盖try-catch内的return结果

再来一个例子:

    public static int test() {
        int result = 0;
        try {
            result = 1;
            return result;
        } catch (Exception e) {
            result = 2;
            return result;
        } finally {
            result = 3;
            System.out.println("Finally block");
        }
    }

    public static void main(String[] args) {
        System.out.println(FinallyTest.test());
    }
结果:
Finally block
1

先不急于解释这种现象,再看一个类似的例子

 public static StringBuilder test() {
        StringBuilder builder = new StringBuilder("hello");
        try {
            return builder;
        } catch (Exception e) {
            return null;
        } finally {
            builder.append("world");
            System.out.println("Finally block");
        }
    }

    public static void main(String[] args) {
        System.out.println(FinallyTest.test());
    }
结果:
Finally block
hello world

对比前面两个例子是不是更加疑惑了,但其实原因特别简单:

  一个方法内部定义的变量都是存储在栈中的,当这个函数结束后,其对应的栈就会被系统回收,此时其方法内部定义的变量将不存在了,因此return在返回的时候不是直接返回方法中的变量的值,而是复制一份,然后返回.

  因此,对于前一个例子当中,由于是基本类型的数据,所有复制的是变量的数值,并且这个复制过程是在执行finally之前的,所有finally内修改基本类型的值没能生效,因为要输出的值早已经确定了

  而后一个例子中是引用类型,复制的时候只是复制的对象的地址,finally对变量进行修改的时候改变了对应的对象的属性,输出的时候按照地址获取属性,获取的是修改后的属性,所以是有影响的.

#现在知道前面的处理是啥了.如图:

这里写图片描述

是不是已将明了了一些了,那么再来看一个例子:

    public static String test() {
        StringBuilder builder = new StringBuilder("hello");
        try {
            return builder.toString();
        } catch (Exception e) {
            return null;
        } finally {
            builder.append(" world");
            System.out.println("Finally block");
        }
    }

    public static void main(String[] args) {
        System.out.println(FinallyTest.test());
    }
输出结果
Finally block
hello

细心的同学应该不会被坑到,finally内的修改没有生效,原因在于复制的时候不是复制的StringBuilder的地址,而是一个字符串的地址,当然也有同学会说String也是引用类型,finally内的代码修改了对应地址的数据,但是要注意String是一个不可变类,builder调用的append方法并没有对"hello"进行任何修改,之前String的地址对应的值是不会变化的.所以finally内的修改没有生效.有的同学有疑惑,关于String , StringBuilder等对象的区别请参考这篇博客:Character , String , StringBuffer , StringBuilder , StringTokenizer 的区别.

为了对比那再看一个例子:

 static class TestEntity {
        String mString;
        StringBuilder mBuilder;

        public TestEntity(String string, StringBuilder builder) {
            mString = string;
            mBuilder = builder;
        }

        public StringBuilder getBuilder() {
            return mBuilder;
        }
    }

    public static StringBuilder test() {
        TestEntity entity = new TestEntity("hello", new StringBuilder("world"));
        try {
            return entity.getBuilder();
        } catch (Exception e) {
            return null;
        } finally {
            entity.getBuilder().append(" world");
            System.out.println("Finally block");
        }
    }

    public static void main(String[] args) {
        System.out.println(FinallyTest.test());
    }

应该已经猜到结果了

Finally block
world world

原因上面都提到了,StringBuilder是引用类型并且是可变的,所以finally内的修改会生效.

结束~

有不足的地方欢迎指出,另外建了个新手交流Android开发的QQ群,欢迎加入.

群号:375276053
<think>好的,我现在要回答用户关于“在函数里return能终止for循环?”的问题。首先,我需要确认用户的问题核心在哪里。可能用户在使用函数时遇到了循环无法正确终止的情况,或者想了解return在循环中的作用。 首先,我应该回忆一下编程中的基本概念。在大多数编程语言中,return语句的作用是立即退出当前函数,并返回一个值。那在函数内部的循环中,比如for循环,一旦执行到return,会发生什么呢? 需要分情况讨论。比如,在函数内部的for循环里,当执行到return时,函数会立即结束,循环自然也会终止。这时候return不仅终止了循环,还退出了整个函数。举个例子,假设有一个函数在循环中查找某个元素,找到后立即返回,这样后面的循环就不会执行了。 但用户可能存在的误区是认为return只能终止循环,但实际上它终止的是整个函数。如果在循环后面还有其他代码,那些代码也不会执行了。这一点需要明确说明。 然后,可能需要对比一下break和return的区别。break只是跳出当前循环,而return是跳出整个函数。比如,在函数中使用break,循环会终止,但函数会继续执行循环之后的代码。而使用return的话,函数直接结束,后面的所有代码都不执行了。 另外,不同编程语言的行为是否一致?比如在Python、JavaScript、Java中,return在函数内的循环里的行为是否相同?一般来说,这些语言中return的作用都是终止函数执行,所以行为应该一致。不过最好还是指出,虽然大多数语言如此,但最好参考具体语言的文档。 用户可能的另一个疑问是,如果循环嵌套在函数中的其他结构里,比如if语句中,return是否仍然有效。这时候应该说明,无论return处于函数的哪个位置,一旦执行,函数就会立即结束。 还需要考虑是否有例外情况。比如,如果在finally块中使用return(如在Java或Python中),可能会有不同的行为,但这可能超出用户当前的问题范围。不过可以简单提及,但主要关注一般情况。 接下来,我应该组织回答的结构。首先明确回答“是的,return会终止循环,并且终止整个函数”。然后通过例子说明,比如一个函数内部有for循环,当满足条件时return,循环和函数都停止。再对比break的情况,说明两者的不同。最后总结使用场景,帮助用户理解何时使用return或break。 另外,要注意用户可能对术语不太熟悉,所以语言要尽量通俗,避免过于技术化。同时,例子要简洁明了,用常见的场景,比如搜索数组中的元素,找到后返回。 最后,确保回答准确,没有错误。比如,在Python中,函数内循环中使用return确实会立即退出函数。可以测试一下简单代码,确认行为是否符合预期。例如: def find_first_even(numbers): for num in numbers: if num % 2 == 0: return num return None 这个函数在找到第一个偶数时立即返回,循环终止,函数结束。如果没找到,循环结束后返回None。这验证了return在循环中的作用。 总结思考过程后,就可以组织成用户容易理解的回答,分点说明,结构清晰。</think>是的,在函数中使用`return`语句**会立即终止整个函数的执行**,自然也会终止函数内部正在运行的`for`循环。这是`return`和`break`的本质区别: --- ### 举个直观例子 🌰 ```python def test(): for i in range(5): print(i) if i == 2: return # 触发return print("循环结束后才会执行这里") test() # 输出结果: # 0 # 1 # 2 ``` - ✅ **现象**:当`i=2`时触发`return`,循环立即终止,函数直接退出,后续的`i=3,4`不再执行,函数末尾的`print`也不会执行。 - ❌ **对比`break`**:若将`return`改为`break`,只会终止循环,函数会继续执行最后的`print`语句。 --- ### 核心规则 📌 1. **穿透性终止** `return`会直接终止**整个函数**,无论它嵌套在多少层循环或条件判断中。 2. **典型应用场景** 常用于函数内部**提前返回结果**,例如: ```python def find_target(lst, target): for item in lst: if item == target: return True # 找到目标,立即终止循环并返回 return False # 循环完整执行后返回 ``` --- ### 对比总结 🆚 | 语句 | 作用范围 | 后续代码执行 | |---------|----------------|----------------------| | `return`| 终止整个函数 | 函数内所有代码不再执行 | | `break` | 仅终止当前循环 | 循环外的代码继续执行 | 根据需求选择:若只需终止循环但继续执行函数逻辑,用`break`;若找到结果需彻底退出函数,用`return`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值