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

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

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

拋出異常

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

throw new IllegalArgumentException

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

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

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

捕獲異常

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í)行過(guò)程中出現(xiàn)異常,將逐個(gè)檢測(cè)每個(gè) catch 塊,在上面的例子,如果打開(kāi)文件出現(xiàn)異常,將先檢查是否是 FileNotFoundException 異常,如果不是,再檢查是否是 IOException,如果還不是,在終止 try-catch 塊的運(yùn)行,而向上傳遞這個(gè)異常。

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

finally語(yǔ)句

Scala 也支持 finally 語(yǔ)句,你可以在 finally 塊中添加一些代碼,這些代碼不管 try 塊是否拋出異常,都會(huì)執(zhí)行。比如,你可以在 finally 塊中添加代碼保證關(guān)閉已經(jīng)打開(kāi)的文件,而不管前面代碼中是否出現(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 也生成某個(gè)值,比如下面的例子嘗試分析一個(gè) URL,如果輸入的 URL 無(wú)效,則使用缺省的 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 塊用來(lái)做些清理工作,而不應(yīng)該產(chǎn)生結(jié)果,但如果在 finally 塊中使用 return 來(lái)返回某個(gè)值,這個(gè)值將覆蓋 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)鍵的一點(diǎn)是避免在 finally 生成返回值,而只用來(lái)做些清理工作,比如關(guān)閉文件。