Java 中关于 try、catch、finally 中的细节分析和注意点

   <!--单元测试3个-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
package com.ruoyi.web.controller.platform;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * Java 中关于 try、catch、finally 中的细节分析
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class TryCatchFinally {
    private final static Logger logger = LoggerFactory.getLogger(TryCatchFinally.class);


    public String test1() {
        String t = "";
        try {
            t = "try";
            return t;
        } catch (Exception e) {
            t = "catch";
            return t;
        } finally {
            t = "finally";
        }
    }

    /**
     * 首先程序执行try语句块,把变量t赋值为try,由于没有发现异常,
     * 接下来执行finally语句块,把变量t赋值为finally,然后return t,则t的值是finally,最后t的值就是finally,程序结果应该显示finally,
     * 但是实际结果为try。
     */
    @Test
    public void result1() {
        logger.info("=============test1返回结果:{}===============", test1());
    }


    public String test2() {
        String t = "";

        try {
            t = "try";
            return t;
        } catch (Exception e) {
            // result = "catch";
            t = "catch";
            return t;
        } finally {
            t = "finally";
            return t;
        }
    }

    /**
     * 我们发现try语句中的return语句给忽略。
     * 可能jvm认为一个方法里面有两个return语句并没有太大的意义,所以try中的return语句给忽略了,
     * 直接起作用的是finally中的return语句,所以这次返回的是finally。
     */
    @Test
    public void result2() {
        logger.info("=============test2返回结果:{}===============", test2());
    }

    public String test3() {
        String t = "";

        try {
            t = "try";
            Integer.parseInt(null);
            return t;
        } catch (Exception e) {
            t = "catch";
            return t;
        } finally {
            t = "finally";
            logger.info("########finally的值是{}###########", t);

        }
    }

    /**
     * 这里面try语句里面会抛出 java.lang.NumberFormatException,所以程序会先执行catch语句中的逻辑,t赋值为catch,
     * 在执行return之前,会把返回值保存到一个临时变量里面t ',
     * 执行finally的逻辑,t赋值为finally,但是返回值和t',
     * 所以变量t的值和返回值已经没有关系了,返回的是catch
     */
    @Test
    public void result3() {
        logger.info("=============test3返回结果:{}===============", test3());
    }

    public String test4() {
        String t = "";

        try {
            t = "try";
            Integer.parseInt(null);
            return t;
        } catch (Exception e) {
            t = "catch";
            return t;
        } finally {
            t = "finally";
            return t;
        }
    }

    /**
     * 这个和test2有点类似,由于try语句里面抛出异常,程序转入catch语句块,
     * catch语句在执行return语句之前执行finally,
     * 而finally语句有return,则直接执行finally的语句值,返回finally
     */
    @Test
    public void result4() {
        logger.info("=============test4返回结果:{}===============", test4());
    }

    public String test5() {
        String t = "";

        try {
            t = "try";
            Integer.parseInt(null);
            return t;
        } catch (Exception e) {
            t = "catch";
            Integer.parseInt(null);
            return t;
        } finally {
            t = "finally";
            //return t;
        }
    }

    /**
     * 这个例子在catch语句块添加了Integer.parser(null)语句,强制抛出了一个异常。
     * 然后finally语句块里面没有return语句。
     * 继续分析一下,由于try语句抛出异常,程序进入catch语句块,catch语句块又抛出一个异常,说明catch语句要退出,
     * 则执行finally语句块,对t进行赋值。然后catch语句块里面抛出异常。结果是抛出java.lang.NumberFormatException异常
     */
    @Test
    public void result5() {
        logger.info("=============test5返回结果:{}===============", test5());
    }

    public String test6() {
        String t = "";

        try {
            t = "try";
            Integer.parseInt(null);
            return t;
        } catch (Exception e) {
            t = "catch";
            Integer.parseInt(null);
            return t;
        } finally {
            t = "finally";
            return t;
        }
    }

    /**
     * 这个例子和test5例子中唯一不同的是,这个例子里面finally 语句里面有return语句块。
     * try catch中运行的逻辑和上面例子一样,当catch语句块里面抛出异常之后,进入finally语句块,然后返回t。
     * 则程序忽略catch语句块里面抛出的异常信息,直接返回t对应的值 也就是finally。方法不会抛出异常
     */
    @Test
    public void result6() {
        logger.info("=============test6返回结果:{}===============", test6());
    }

    public String test7() {
        String t = "";

        try {
            t = "try";
            Integer.parseInt(null);
            return t;
        } catch (NullPointerException e) {
            t = "catch";
            return t;
        } finally {
            t = "finally";
        }
    }

    /**
     * 这个例子里面catch语句里面catch的是NPE异常,而不是java.lang.NumberFormatException异常,
     * 所以不会进入catch语句块,直接进入finally语句块,finally对s赋值之后,
     * 由try语句抛出java.lang.NumberFormatException异常。
     */
    @Test
    public void result7() {
        logger.info("=============test7返回结果:{}===============", test7());
    }

    public String test8() {
        String t = "";

        try {
            t = "try";
            Integer.parseInt(null);
            return t;
        } catch (NullPointerException e) {
            t = "catch";
            return t;
        } finally {
            t = "finally";
            return t;
        }
    }

    /**
     * 和上面test7()的例子中try catch的逻辑相同,try语句执行完成执行finally语句,finally赋值s 并且返回s ,最后程序结果返回finally
     */
    @Test
    public void result8() {
        logger.info("=============test8返回结果:{}===============", test8());
    }

    public String test9() {
        String t = "";

        try {
            t = "try";
            return t;
        } catch (Exception e) {
            t = "catch";
            return t;
        } finally {
            t = "finally";
            String.valueOf(null);
            return t;
        }
    }

    /**
     * 这个例子中,对finally语句中添加了String.valueOf(null), 强制抛出NPE异常。
     * 首先程序执行try语句,在返回执行,执行finally语句块,finally语句抛出NPE(NullPointerException)异常,整个结果返回NPE异常。
     */
    @Test
    public void result9() {
        logger.info("=============test9返回结果:{}===============", test9());
    }
}

对以上所有的例子进行总结

  1. try、catch、finally语句中,在如果try语句有return语句,则返回的之后当前try中变量此时对应的值,此后对变量做任何的修改,都不影响try中return的返回值
  2. 如果finally块中有return 语句,则返回try或catch中的返回语句忽略。
  3. 如果finally块中抛出异常,则整个try、catch、finally块中抛出异常

所以使用try、catch、finally语句块中需要注意的是

  1. 尽量在try或者catch中使用return语句。通过finally块中达到对try或者catch返回值修改是不可行的。
  2. finally块中避免使用return语句,因为finally块中如果使用return语句,会显示的消化掉try、catch块中的异常信息,屏蔽了错误的发生
  3. finally块中避免再次抛出异常,否则整个包含try语句块的方法回抛出异常,并且会消化掉try、catch块中的异常
Java try-catch-finally 语句用于捕获和处理异常。它的基本语法如下: ```java try { // 可能会抛出异常的代码块 } catch (ExceptionType1 e1) { // 处理异常类型1的代码块 } catch (ExceptionType2 e2) { // 处理异常类型2的代码块 } finally { // 无论是否发生异常,都会执行的代码块 } ``` 在 try,你可以放置可能会抛出异常的代码。如果在执行 try的代码时发生了异常,那么就会跳到相应的 catch进行异常处理。catch 块可以有多个,每个 catch 块用于捕获不同类型的异常,并提供相应的处理逻辑。catch的参数 e1、e2 是异常对象,你可以使用它们来获取有关异常的信息。 无论是否发生异常,finally的代码都会被执行。finally 块通常用于释放资源或执行清理操作,确保在任何情况下都会执行。 如果在 try发生了异常,并且没有相应的 catch 块来处理该异常,那么该异常将被传递给上层调用栈,直到找到合适的 catch 块进行处理,或者如果没有找到任何 catch 块,则程序将终止。 以下是一个简单的示例: ```java try { int result = divide(10, 0); System.out.println("结果:" + result); } catch (ArithmeticException e) { System.out.println("除数不能为零!"); } finally { System.out.println("finally的代码"); } public static int divide(int dividend, int divisor) { return dividend / divisor; } ``` 在上面的示例,divide 方法会抛出一个 ArithmeticException 异常,因为除数为零。在 catch,我们对该异常进行处理,并输出相应的信息。无论是否发生异常,finally的代码都会执行,输出 "finally的代码"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值