17.4. Klauzula catch

Wyrażenie try może zawierać klauzulę catch, składającą się ze słowa kluczowego catch, po którym, w nawiasach klamrowych, znajduje się lista wyrażeń case, podobna do występującej w przypadku instrukcji match, przy czym wzorce znajdujące się w kolejnych klauzulach case powinny dopasowywać obiekt reprezentujący wyjątek, a dokładniej obiekt będący typu java.lang.Throwable lub jego podtypu. Poniższe wyrażenie try z klauzulą case nie kompiluje się, gdyż wzorzec znajdujący się w klauzuli case nie jest odpowiedniego typu.

scala> try println("hi") catch { case _: Int => }
<console>:11: error: pattern type is incompatible with expected type;
 found   : Int
 required: Throwable
       try println("hi") catch { case _: Int => }
                                         ^

Plik Try2.scala zawiera definicję metody hello, w której znajduje się wywołanie metody greet_!, zdefiniowanej w pliku Throw1.scala, opakowane wyrażeniem try z klauzulą catch. W klauzuli catch znajdują się klauzule case dopasowujące różne typy wyjątków.

Plik Try2.scala:
def hello(n: Int) =
  try {
    greet_!("Hello", n)
  } catch {
    case e: IllegalArgumentException =>
      println("Illegal argument: " + e.getMessage)
      "Hello." 
    case e: RuntimeException => 
  }

Jeśli wykonywanie bloku kodu znajdującego się po słowie kluczowym try zakończy się z powodu wygenerowania w nim wyjątku oraz jeśli ten wyjątek może zostać dopasowany do jednego ze wzorców znajdujących się w klauzulach case bloku catch, to kod znajdujący się po podwójnej strzałce w pierwszej z klauzul case, która dopasowała obiekt wyjątku, zostaje wykonany. Wynikiem całego wyrażenia try staje się wynik wykonania tego kodu. W poniższym wywołaniu metody hello metoda greet_! wyrzuca wyjątek typu IllegalArgumentException, który zostaje przechwycony i obsłużony w metodzie hello. Wynikiem metody hello staje się łańcuch znaków „Hello.” z wiersza .

scala> :load Throw1.scala
Loading Throw1.scala...
greet_$bang: (greeting: String, n: Int)String

scala> :load Try2.scala
Loading Try2.scala...
hello: (n: Int)Any
scala> hello(-1)
Illegal argument: The number must be positive.
res1: Any = Hello.

Po strzałce nie musi znajdować się żadne wyrażenie do wykonania. Taka sytuacja ma miejsce w metodzie hello w wierszu . Jeśli po strzałce nie znajdują się żadne instrukcje, to wykonywanie wyrażenia try z klauzulą catch kończy się. W poniższym wywołaniu metody hello metoda greet_! wyrzuca wyjątek typu RuntimeException, który zostaje przechwycony w metodzie hello. Wynikiem działania metody jest wartość ().

scala> hello(0)
res2: Any = ()

W bloku catch może zostać zgłoszony wyjątek. Taki wyjątek staje się wynikiem całego wyrażenia try. Taka sytuacja ma miejsce w poniższym przykładzie.

scala> try throw new Exception("1") catch {
     |   case ex: Exception =>
     |     println("ex: "+ex)
     |     throw new Exception("2")
     | }
ex: java.lang.Exception: 1
java.lang.Exception: 2
  at .liftedTree1$1(<console>:14)
  ... 41 elided

Kolejny przykład pokazuje sytuację, w której przechwycony wyjątek jest ponownie wyrzucany w bloku catch.

scala> try throw new Exception("1") catch {
     |   case ex: Exception =>
     |     println("ex: "+ex)
     |     throw ex
     | }
ex: java.lang.Exception: 1
java.lang.Exception: 1
  at .liftedTree1$1(<console>:11)
  ... 41 elided

Jeśli wykonanie bloku kodu znajdującego się po słowie kluczowym try zakończy się z powodu wygenerowania wyjątku, ale jeśli wygenerowany obiekt wyjątku nie zostanie dopasowany do żadnego z wzorców w klauzulach case, to wykonywanie całego wyrażenia try kończy się wyrzuceniem tego wyjątku. W poniższym wywołaniu metody hello metoda greet_! wyrzuca wyjątek typu Exception, który nie zostaje przechwycony.

scala> hello(8)
java.lang.Exception: Number too big: 8
  at .greet_$bang(<console>:13)
  at .hello(<console>:13)
  ... 33 elided

Jeśli wykonanie wyrażenia znajdującego się po słowie kluczowym try zakończy się bez generowania wyjątku, to jego wynik staje się wynikiem całego wyrażenia try. W poniższym wywołaniu metody hello metoda greet_! nie wyrzuca wyjątku, a wynik tej metody staje się wynikiem wywołania metody hello.

scala> hello(4)
res6: Any = Hello!!!!

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.