程式扎記: [Scala 小學堂] Scala Gossic : 起步走 - 內建控制結構 (try 運算式)

標籤

2016年4月14日 星期四

[Scala 小學堂] Scala Gossic : 起步走 - 內建控制結構 (try 運算式)

轉載自 這裡 
前言 : 
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. 從一些簡單的語法開始,了解 Scala 的許多特性,所以就算是起步走,東西也夠多了. 簡單的小程式可以使用 scala 指令,編譯的事就交給 scalac,編譯想快點就用 fsc. (Scala 官網), 運算式有傳回值,迴圈沒有,對了!Scala 沒有 break 與 continue. 

try 運算式 : 
如果你撰寫了這段程式 : 
  1. val filename = args(0)  
使用者如果沒有提供命令列引數,則 args 的長度會是0,存取索引 0 就會發生超出陣列索引範圍的錯誤,在 Scala 中,會丟出 java.lang.ArrayIndexOutOfBoundsException。你可以使用 isEmpty 來測試 args 是否為空: 
  1. if(args.isEmpty)  
  2.         throw new IllegalArgumentException("Please provide arguments")  
  3. val filename = args(0)  
  4. // Continue app  
另一個方式是使用 try...catch 語句,在使用者沒有提供引數時,於 catch 中捕捉例外並顯示錯誤訊息 : 
- Try2.scala 代碼 : 
  1. try{  
  2.         val filename = args(0)  
  3.         // Continue app  
  4. }catch{  
  5.         case ex: ArrayIndexOutOfBoundsException => println("Please provide arguments!")  
  6. }  
程式會嘗試取得 args(0),如果丟出例外,而在 catch 中有撰寫對應的 case 比對,則會執行對應的處理程式。如果有多個例外類似要比對,則可以撰寫多個 case,如果最後有一定得處理的程式,則可以撰寫 finally 區塊,例如 : 
- Try3.scala 代碼 :
  1. import java.io._  
  2. try{  
  3.         val reader = new FileReader(args(0))  
  4.         try{  
  5.                 //Do some operation  
  6.         } catch {  
  7.                 case ex: IOException => println("IO Error!")  
  8.         } finally {  
  9.                 reader.close()  
  10.         }  
  11. catch {  
  12.         case ex: ArrayIndexOutOfBoundsException => println("Please provide arguments")  
  13.         case ex: FileNotFoundException => println("File not found: "+args(0))  
  14. }  

在 Scala 中,並不要求你得處理受檢例外(Checked Exception)(參考 Java 的 例外的繼承架構), 你只需針對感興趣或有能力處理的例外加以捕捉並處理即可,如果在例外發生的當時情境下無力處理,你什麼事都不用作(不用寫 try...catch 也不用在 函式或方法上用 throws 宣告),將處理留給後續的呼叫者來善後在 Java 中,受檢例外是由編譯器進行檢查,Scala 編譯器不檢查受檢例外,事實上,Scala 也沒有 throws 關鍵字。如果你要讓某個方法在編譯後產生的位元碼中,有 Java 中 throws 宣告,以便給 Java 程式使用時可以得到 受檢例外檢查機制,則可以使用 @throws 標注,標注的使用之後還會說明). 在Scala 中,try...catch...finally 是運算式,所以會有運算結果,例如你可以撰寫這樣的程式碼 : 
- Try4.scala 代碼 :
  1. val filename =  
  2. try {  
  3.         args(0)  
  4. catch {  
  5.         case ex: ArrayIndexOutOfBoundsException => "default.properties"  
  6. }  
  7. println("Filename: "+filename)  

如 果有提供命令列引數,則將 filename 設定為所提供的值,否則就是設定為 default.properties。你也可以在 finally 中提供傳回 值,不過並不鼓勵,因為 finally 中基本上是用來關閉、釋放某些資源或作些善後動作。如果你要在 finally 中提供傳回值,要注意一下以下兩個程式片段的不同 : 
  1. def doSome = try { 1 } finally { 2 }  
如果你呼叫 doSome(),則以上程式片段會傳回 try 區塊中的1,但如果是 : 
  1. def doSome: Int = try { return 1 } finally { return 2 }  
因為你明確地使用 return,這個程式片段會傳回 2(這個行為與 Java 是相同的)。如先前所提到的,在finally中並不建議有傳回值,而僅用於關閉、釋放資源或作些善後動作明確地使用 return 在 Scala 中也是不鼓勵的,因為容易破壞程式的結構,在 Scala 中使用 return 就無法使用類 型推斷,像以上定義函式時,就得明確定義函式的傳回值型態,另外,return 在 Scala 中只能用於函式之中). 在Scala 中處理例外,要注意一下例外比對的順序,例如 : 
- Try5.scala 代碼 :
  1. val filename =  
  2. try{  
  3.         args(0)  
  4. catch {  
  5.         case ex: Exception => "Exception"//Do some operation  
  6.         case ex: ArrayIndexOutOfBoundsException => "BoundsException"//Do some operation  
  7. }  
  8. println("Filename= "+filename)  

由於 Exception 是 ArrayIndexOutOfBoundsException 的父類別,所以這個程式片段,只會符到到第一個 Exception,第二個 ArrayIndexOutOfBoundsException 永遠不會被比對到,Scala不會提出警訊(Java的編譯器會對這部份作檢查),程式會照常執行. 

Supplement 
Tutorialspoint - Scala Exception Handling
起步走 - 內建控制結構 (if 運算式) 
起步走 - 內建控制結構 (for 運算式) 
起步走 - 內建控制結構 (while 迴圈) 
起步走 - 內建控制結構 (match 運算式) 
起步走 - 內建控制結構 (try 運算式)

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!