17.5. Klauzula finally
Wyrażenie try z klauzulą finally ma postać try b finally e, gdzie try i finally to słowa kluczowe, a b i e to wyrażenia. Wykonanie wyrażenia try w tej postaci polega na tym, że najpierw jest wykonywane wyrażenie b, a następnie wyrażenie e. Wyrażenie e jest wykonywane również wtedy, gdy wykonywanie wyrażenia b zakończy się wyjątkiem lub wykonaniem wyrażenia return. W każdym z poniższych przykładów instrukcja println znajdująca się po słowie kluczowym finally zostaje wykonana, ale jej rezultat (typu Unit) jest ignorowany i nie staje się wynikiem całego wyrażenia try. Drugi przykład jest umieszczony w metodzie z uwagi na użycie wyrażenia return.
scala> try { println("try"); "try" } finally println("finally")
try
finally
res0: String = try
scala> def m(): String = try return "try" finally println("finally")
m: ()String
scala> m()
finally
res1: String = try
scala> try throw new Exception("try") finally println("finally")
finally
java.lang.Exception: try
... 33 elided
Wynik całego wyrażenia try b finally e nie zawsze musi być równy wynikowi ewaluacji wyrażenia b. Jeśli ewaluacja wyrażenia e zakończy się zgłoszeniem wyjątku, to całe wyrażenie try kończy się zgłoszeniem tego wyjątku. Na wynik całego wyrażenia nie wpływa wtedy to, jak zakończyło się wyrażenie b, to znaczy czy zakończyło się zgłoszeniem wyjątku, czy też nie. Każde z poniższych wyrażeń try kończą się zgłoszeniem wyjątku z wyrażenia throw znajdującego się po klauzuli finally.
scala> try 1 finally throw new Exception("finally")
java.lang.Exception: finally
... 33 elided
scala> def m2(): Int = try return 1 finally throw new Exception("finally")
m2: ()Int
scala> m2()
java.lang.Exception: finally
at .m2(<console>:10)
... 33 elided
scala> try throw new Exception("1") finally throw new Exception("finally")
java.lang.Exception: finally
... 33 elided
W klauzuli finally zdefiniowanej w metodzie może być użyte wyrażenie return. W takim przypadku wynik metody nie zależy od tego, jak zakończone zostało wykonanie wyrażenia try. Każda z metod zdefiniowanych w pliku Return3.scala zawiera takie samo wyrażenie return w klauzuli finally.
Plik Return3.scala: def f1:Int = try 1 finally return 2 def f2:Int = try return 1 finally return 2 def f3:Int = try throw new Exception finally return 2
Każda z tych metod zwraca taki sam rezultat, niezależnie od tego, że w każdej z nich jest różna treść wyrażenia znajdującego się po słowie kluczowym try.
scala> :load Return3.scala Loading Return3.scala... f1: Int f2: Int f3: Int scala> f1 res6: Int = 2 scala> f2 res7: Int = 2 scala> f3 res8: Int = 2
Plik Return3.scala:
def f1:Int = try 1 finally return 2
def f2:Int = try return 1 finally return 2
def f3:Int = try throw new Exception finally return 2
