鍍金池/ 教程/ Scala/ try 表達(dá)式處理異常
包對象
Ordered Trait
組合和繼承–定義 final 成員
基本數(shù)據(jù)類型
Match 表達(dá)式
類和對象 (三)
操作基本數(shù)據(jù)類型
for 表達(dá)式
組合和繼承–重載成員函數(shù)和方法
類和對象 (二)
組合和繼承–定義 factory 對象
組合和繼承–多態(tài)和動態(tài)綁定
Trait 的基本概念
if 表達(dá)式
組合和繼承–抽象類
函數(shù)–函數(shù)字面量的一些簡化寫法
while 循環(huán)
組合和繼承–使用組合還是繼承?
訪問控制修飾符
Trait 示例–Rectangular 對象
組合和繼承–定義參數(shù)化成員變量
組合和繼承–定義無參數(shù)方法
類和對象 (一)
函數(shù)–閉包
函數(shù)–類成員函數(shù)
Scala 基本數(shù)據(jù)類型的實現(xiàn)方法
try 表達(dá)式處理異常
選擇瘦接口還是胖接口設(shè)計?
組合和繼承–小結(jié)
創(chuàng)建新的控制結(jié)構(gòu)
使用 import
為訪問控制修飾符添加作用域
Scala 的類層次關(guān)系
類和對象 (五)
傳名參數(shù)
柯里化函數(shù)
函數(shù)–頭等公民
組合和組合和繼承–定義 heighten 和 widen 函數(shù)
使用 Package–將代碼放入包中
隱含的 import
所有類的公共子類–底層類型
進(jìn)一步 Scala
函數(shù)–局部函數(shù)
引用包中的代碼
組合和繼承–使用 override 修飾符
組合和繼承–實現(xiàn)類 Element 的 above,beside 和 toString()方法
類和對象 (四)
函數(shù)–尾遞歸
沒有“break”和“continue”的日子
組合和繼承–調(diào)用基類構(gòu)造函數(shù)
減低代碼重復(fù)
函數(shù)–函數(shù)–可變參數(shù),命名參數(shù),缺省參數(shù)
起步 Scala
組合和繼承–擴(kuò)展類
函數(shù)–部分應(yīng)用的函數(shù)
開始神奇的 Scala編程之旅
組合和繼承–概述
Trait 用來實現(xiàn)可疊加的修改操作

try 表達(dá)式處理異常

Scala 的異常處理和其它語言比如 Java 類似,一個方法可以通過拋出異常的方法而不返回值的方式終止相關(guān)代碼的運(yùn)行。調(diào)用函數(shù)可以捕獲這個異常作出相應(yīng)的處理或者直接退出,在這種情況下,異常會傳遞給調(diào)用函數(shù)的調(diào)用者,依次向上傳遞,直到有方法處理這個異常。

拋出異常

Scala 拋出異常的方法和 Java一樣,使用 throw 方法,例如,拋出一個新的參數(shù)異常:

throw new IllegalArgumentException

盡管看起來似乎有些自相矛盾,Scala 中,throw 也是一個表達(dá)式,也是有返回值的,比如下面的例子:

val half =
  if (n % 2 == 0)
    n/2
  else
    throw new RuntimeException("n must be even")

當(dāng) n 為偶數(shù)時,n 初始化為 n 的一半,而如果 n 為奇數(shù),將在初始化 half 之前就拋出異常,正因為如此,可以把 throw 的返回值的類型為任意類型。技術(shù)上來說,拋出異常的類型為 Nothing。對于說明的例子來說整個 if 表達(dá)式的類型為可以計算出值的那個分支的類型,如果 n 為 Int,那么 if 表示式的類型也是 Int 類型,而不需要考慮 throw 表達(dá)式的類型。

捕獲異常

Scala 捕獲異常的方法和后面介紹的“模式匹配”的使用方法是一致的。比如:

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
try {
  val f = new FileReader("input.txt")
} catch {
  case ex: FileNotFoundException => //handle missing file
  case ex: IOException => //handle other I/O error
}

模式匹配將在后面介紹,try-catch 表達(dá)式的基本用法和 Java 一樣,如果 try 塊中代碼在執(zhí)行過程中出現(xiàn)異常,將逐個檢測每個 catch 塊,在上面的例子,如果打開文件出現(xiàn)異常,將先檢查是否是 FileNotFoundException 異常,如果不是,再檢查是否是 IOException,如果還不是,在終止 try-catch 塊的運(yùn)行,而向上傳遞這個異常。

注意:和 Java 異常處理不同的一點是,Scala 不需要你捕獲 checked 的異常,這點和 C# 一樣,也不需要使用 throw 來聲明某個異常,當(dāng)然如果有需要還是可以通過 @throw 來聲明一個異常,但這不是必須的。

finally語句

Scala 也支持 finally 語句,你可以在 finally 塊中添加一些代碼,這些代碼不管 try 塊是否拋出異常,都會執(zhí)行。比如,你可以在 finally 塊中添加代碼保證關(guān)閉已經(jīng)打開的文件,而不管前面代碼中是否出現(xiàn)異常。

import java.io.FileReader
val file = new FileReader("input.txt")
try {
  //use the file
} finally {
  file.close()
}

生成返回值

和大部分Scala 控制結(jié)構(gòu)一樣,Scala 的 try-catch-finally 也生成某個值,比如下面的例子嘗試分析一個 URL,如果輸入的 URL 無效,則使用缺省的 URL 鏈接地址:

import java.net.URL
import java.net.MalformedURLException
def urlFor(path:String) =
  try {
    new URL(path)
  } catch {
    case e: MalformedURLException =>
      new URL("http://www.scala-lang.org")
  }

通常情況下,finally 塊用來做些清理工作,而不應(yīng)該產(chǎn)生結(jié)果,但如果在 finally 塊中使用 return 來返回某個值,這個值將覆蓋 try-catch 產(chǎn)生的結(jié)果,比如:

scala> def f(): Int = try { return 1 } finally { return 2}
f: ()Int
scala> f
res0: Int = 2

而下面的代碼:

scala> def g() :Int = try 1 finally 2
g: ()Int
scala> g
res0: Int = 1

結(jié)果卻是 1,上面兩種情況常常使得程序員產(chǎn)生困惑,因此關(guān)鍵的一點是避免在 finally 生成返回值,而只用來做些清理工作,比如關(guān)閉文件。