連環清潔工之特殊任務–java資源如何關閉?
- 2019 年 10 月 3 日
- 筆記
小C是一名特殊的黑客,他專門為黑客提供服務,掃除黑客攻擊的痕迹,避免被查到為何人攻擊。
今天他正興緻勃勃的玩遊戲《連環清潔工》,連環清潔工是由iFun4all S.A.製作發行的一款犯罪題材動作冒險類遊戲,故事劇情講述的是一個專門山寨別人的殺手,專門模仿最近發生的大案要案,製造類似的兇殺案。遊戲中玩家扮演一名專業兇案現場清掃人員,為客戶處理屍體、清理血跡、隱藏兇器等犯罪證據,玩家接受任務的時候不能問任何問題。
突然接到小白請求幫助的緊急電話,註:小白是小C入侵小白的電腦後認識的,詳情太多,參見詳細地址https://cloud.tencent.com/developer/news/333203。
原來小白在學習java,碰到一個編程問題:文件操作關閉資源的時候會莫名其妙的報錯。程式碼如下:
public void openFile() throws IOException { FileReader reader = new FileReader("someFile"); int i=0; while(i != -1){ i = reader.read(); System.out.println((char) i ); } reader.close(); System.out.println("--- File End ---"); }
小C針對小白剛剛編程的經歷,採用循循誘導的方式。
小C:上面的程式碼是不是沒有捕獲異常?是不是可以把異常捕獲到,再分析異常原因?
小白:對哦,那我使用try 。。catch試試
public void openFile(){ try { // constructor may throw FileNotFoundException FileReader reader = new FileReader("someFile"); int i=0; while(i != -1){ //reader.read() may throw IOException i = reader.read(); System.out.println((char) i ); } reader.close(); System.out.println("--- File End ---"); } catch (FileNotFoundException e) { //do something clever with the exception } catch (IOException e) { //do something clever with the exception } }
小C:做的很不錯,知道捕捉多重異常了!,資源的關閉是不是放到finally比較好?
小白:對哦,我看語法有這樣的,那我重新寫一下
public void openFile() throws IOException { FileReader reader = null; try { reader = new FileReader("someFile"); int i=0; while(i != -1){ i = reader.read(); System.out.println((char) i ); } } catch (FileNotFoundException e) { //do something clever with the exception } catch (IOException e) { //do something clever with the exception }finally { reader.close(); System.out.println("--- File End ---"); } }
小白:哦,還忘掉reader的判斷,再改一下:
public void openFile() throws IOException { FileReader reader = null; try { reader = new FileReader("someFile"); int i=0; while(i != -1){ i = reader.read(); System.out.println((char) i ); } } catch (FileNotFoundException e) { //do something clever with the exception } catch (IOException e) { //do something clever with the exception }finally { if(reader != null){ reader.close(); } reader.close(); System.out.println("--- File End ---"); } }
小C:reader的關閉,是不是還有可能拋出異常,是不是還要捕獲?
小白:是哦,我忘記了,修改後的是這樣的嗎?
public void openFile() throws IOException { FileReader reader = null; try { reader = new FileReader("someFile"); int i=0; while(i != -1){ i = reader.read(); System.out.println((char) i ); } } catch (FileNotFoundException e) { //do something clever with the exception } catch (IOException e) { //do something clever with the exception }finally { if(reader != null){ try { reader.close(); } catch (IOException e) { //do something clever with the exception } } reader.close(); System.out.println("--- File End ---"); } }
小C:程式碼是不是太繁瑣了?有沒有更簡潔的辦法?讓jvm幫你處理一些繁瑣的工作?
小白:聽說過ry-with-resources,但沒有用過。
小C:那你看看這個是否簡潔了一些呢?
public void openFile() throws IOException { try (FileReader reader = new FileReader("someFile")){ ; int i=0; while(i != -1){ i = reader.read(); System.out.println((char) i ); } } catch (FileNotFoundException e) { //do something clever with the exception } catch (IOException e) { //do something clever with the exception } }
把資源放到try()內部, JVM會調用java.lang.AutoCloseable.close() 方法,自動關閉try()內部的資源。
小白:厲害,我學會了。
小C:那我考考你。
public static void main(String[] args) { try { System.out.println("Hello world"); return; } finally { System.out.println("Goodbye world"); } }
這個會列印出什麼結果?
小白:“hello world” 因為return 退出了,finally不能執行。
小C:不對,finally總是會執行的,列印
Hello world
Goodbye world
小白:我明白了,finally總是會執行的。
小C:那可不一定哦,看看這個:
public static void main(String[] args) { try { System.out.println("Hello world"); System.exit(0); } finally { System.out.println("Goodbye world"); } }
小白:不是列印?
Hello world
Goodbye world
小C:不論try語句塊的執行是正常地還是意外地結束,finally語句塊確實都會執行。
然而在這個程式中,try 語句塊根本就沒有結束其執行過程。System.exit 方法
將停止當前執行緒和所有其他當場死亡的執行緒。finally 子句的出現並不能給予線
程繼續去執行的特殊許可權。
如果想要執行,想要使用hook
public static void main(String[] args) { System.out.println("Hello world"); Runtime.getRuntime().addShutdownHook( new Thread() { public void run() { System.out.println("Goodbye world"); } }); System.exit(0); }
小白:好神奇!
小C:學無止境,一起加油!今天到這裡了,我還要繼續我的遊戲呢。
參考資料
【1】http://tutorials.jenkov.com/java-exception-handling/basic-try-catch-finally.html
【2】https://howtodoinjava.com/java/exception-handling/try-catch-finally/
【3】https://howtodoinjava.com/java7/try-with-resources/
【4】java解惑