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塊中的異常
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章