Zadanie 1

Napisz metodę, która jako parametr będzie przyjmowała napis i wypisywała na standardowe wyjście jego długość.

  1. Przekaż do tej metody null i zobacz, jaki wyjątek został zgłoszony.
  2. Otocz wywołanie metody blokiem try-catch, przechwyć ten wyjątek i wypisz na standardowe wyjście ślad stosu wywołań z chwili zgłoszenia wyjątku.
  3. Bezpośrednio po wypisaniu jego śladu zgłoś obsługiwany wyjątek ponownie.
  4. Czy ślady stosu wypisane przez ciebie w bloku catch i przez maszynę wirtualną w chwili przerwania programu są takie same?
  5. Przed zgłoszeniem ponownie obsługiwanego wyjątku wykonaj na nim metodę fillInStackTrace().
  6. Zamiast zgłaszać ponownie obsługiwany wyjątek, zgłoś nowy wyjątek klasy Exception. Zauważ, że wymaga to pewnej dodatkowej zmiany w kodzie.
  7. Dołącz obsługiwany wyjątek do nowo tworzonego wyjątku Exception jako przyczynę jego powstania.

Zadanie 2

Napisz trzy nowe wyjątki oraz metodę, która za każdym wywołaniem będzie losowo zgłaszała jeden z nich.

  1. Otocz wywołanie tej metody instrukcją try-catch zawierającą po jednym bloku catch dla każdego z wyjątków. Niech każdy blok catch wypisuje, który wyjątek złapała.
  2. Sprawdź, co się stanie, jeżeli zmienisz kod metody tak, żeby przestała zgłaszać jeden z wyjątków, ale nadal będzie on wymieniony w klauzuli throws nagłówka metody. Czy metody wywołujące napisaną przez ciebie metodę, ale nie obsługujące tego wyjątku będą musiały nadal go wymieniać w swoich nagłówkach?

Zadanie 3

Napisz program sprawdzający, czy wyjątki zgłoszone w blokach catch mogą być obsłużone przez ten sam blok lub jeden z pozostałych bloków tej samej instrukcji try-catch.

Zadanie 4

Czy deklaracja wyjątków należy do sygnatury metody? Przygotuj przykład, który to rozstrzyga.

Zadanie 5

Dany jest następujący fragment kodu.

import java.io.IOException;

class InnyMożliwyWyjątek extends Exception {}

class Zasób2 {
  Zasób2(int i) {
    //...
  }
  void zarezerwuj() {}
  void używaj() throws IOException {}
  void innaNiebezpiecznaOperacja() throws InnyMożliwyWyjątek {}
  void zwolnij() {}
}

public class ZwalnianieZasobów2 {
  public static void main(String[] args) throws Exception {
    for (int i = 0; i < 10; i++) {
      Zasób2 z = new Zasób2(i);
      try {
        z.zarezerwuj();

        //tu jest niebezpieczny kod
        z.używaj();
        z.innaNiebezpiecznaOperacja();
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //trzeba zwolnić zasób, bo kończy się obrót pętli
        if (i == 3) continue;
        //trzeba zwolnić zasób, bo kończy się cała metoda
        if (i == 8) return;
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //...

        //zwalnianie zasobów
        z.zwolnij();
      } catch (IOException e) {
        //obsługa wyjątku IOException

        //zwalnianie zasobów
        z.zwolnij();
      } catch (InnyMożliwyWyjątek w) {
        //obsługa wyjątku InnyMożliwyWyjątek

        //zwalnianie zasobów
        z.zwolnij();
      } catch (Exception e) {
        //innych wyjątków nie obsługujemy, ale przechwytujemy je na chwilę, żeby zwolnić zasoby
        //złapią się tu również wyjątki niekontrolowane (rozszerzające RuntimeException)

        //zwalnianie zasobów
        z.zwolnij();
        throw e;
      }
    }
  }
}

Zmodyfikuj klasę ZwalnianieZasobów2, aby zwalnianie odbywało się w bloku finally. Sprawdź, czy rzeczywiście zasób jest zwalniany nawet jak blok try jest opuszczany przy pomocy instrukcji return, break i continue.

Zadanie 6

Podczas rezerwowania i zwalniania zasobów zazwyczaj też może wystąpić wyjątek. Użyj pokazanej poniżej klasy Zasób3, w każdym obrocie pętli utwórz dwa zasoby. Następnie zmodyfikuj swoje rozwiązanie poprzedniego zadania tak, aby zawsze oba zasoby były zwalniane. Zadbaj, żeby nie dochodziło do zaginięcia żadnych wyjątków. Możesz założyć, że wykonanie operacji zwolnij() na zamkniętym zasobie jest dozwolone.

class InnyMożliwyWyjątek extends Exception {}
class JeszczeInnyMożliwyWyjątek extends Exception {}

class Zasób3 {
  Zasób3(int i) {
    //...
  }
  void zarezerwuj() throws IOException {}
  void używaj() throws IOException {}
  void innaNiebezpiecznaOperacja() throws InnyMożliwyWyjątek, JeszczeInnyMożliwyWyjątek {}
  void zwolnij() throws IOException {}

Zadanie 7

Sprawdź, czy finally jest wykonywane pomimo wystąpienia wyjątku w bloku catch z tej samej instrukcji.

Zadanie 8

Napisz klasę, której konstruktor zgłasza wyjątek. W metodzie main() utwórz egzemplarz tej klasy i obsłuż wyjątek.

Zadanie 9

Sprawdź, czy konstruktor podklasy nie może obsłużyć wyjątków zgłaszanych przez konstruktor nadklasy.