­

連環清潔工之特殊任務–java資源如何關閉?

  • 2019 年 10 月 3 日
  • 筆記

小C是一名特殊的黑客,他專門為黑客提供服務,掃除黑客攻擊的痕迹,避免被查到為何人攻擊。

java清道夫的特殊任務

 

今天他正興緻勃勃的玩遊戲《連環清潔工》,連環清潔工是由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解惑