Zagadka Java #6

Zagadki Java zawierają różnego rodzaju niuanse języka i „podchwytliwe” fragmenty kodu. Każda następna zagadka będzie zawierała odpowiedź i wyjaśnienie do poprzedniej. Lista wszystkich zagadek.

Jeżeli znasz odpowiedź, podziel się nią w komentarzu!

Zagadka Java #6

Które z poniższych linii kodu klasy SpotTheError spowodują błąd kompilacji i dlaczego?

public class SpotTheError {
  public static final void main(String[] args) {
    long longVal = 9876543210;

    int intVal1 = 1_0;
    int intVal2 = 0xff;

    String $fiveDollars = "$5";
    String #ofPuzzlesSoFar = 6;

    float floatVal1 = 0;
    float floatVal2 = 0.0;

    byte byteVal1 = 1;
    byte byteVal2 = (byte) -129;

    long anotherLong = 1;

    switch (anotherLong) {
      case 0:
        System.out.println("0");
        break;
      default:
        System.out.println(anotherLong);
        break;
    }
  }
}

Odpowiedź do poprzedniej zagadki #5

Poniżej znajdziesz odpowiedź do poprzedniej zagadki.

Próba kompilacja klasy MyExceptionTest zakończy się następującym błędem kompilacji:

MyExceptionTest.java:15: error: exception MyException is never thrown in body of corresponding try statement } catch (MyException e) {} ^ 1 error

Problem występuje w drugiej instrukcji try..catch, w której próbujemy obsłużyć wyjątek rodzaju Checked. O tym, że jest to wyjątek rodzaju Checked świadczy to, że dziedziczy on po klasie Exception, i nie ma w swojej hierarchii dziedziczenia klasy RuntimeException:

class MyException extends Exception {}

Jeżeli wywołanie metody może skutkować rzuceniem wyjątku rodzaju Checked, to, w przeciwieństwie do wyjątków Unchecked, metoda musi zdefiniować taki wyjątek za pomocą klauzuli throws w swojej sygnaturze. Tak dzieje się w przypadku metody m, która definiuje potencjał rzucenia wyjątku MyException:

public static void m() throws MyException {}

Próba wywołania tej metody z wykorzystaniem try..catch jest prawidłowa:

try {
  m();
} catch (MyException e) {}

Jednakże, w przypadku metody m2, która nie definiuje żadnego wyjątku za pomocą throws:

public static void m2() {}

Nie możemy skorzystać z try..catch:

try {
  m2();
} catch (MyException e) {}

Kompilator zaprotestuje – próbujemy złapać wyjątek rodzaju Checked, wywołując metodę, która nie deklaruje możliwości rzucenia takiego wyjątku.

Jest to jedyny błąd, jaki zgłosi kompilator. Dlaczego w przypadku metody m3, która także nie deklaruje rzucania wyjątku, kompilator nie zgłasza podobnego błędu?

public static void m3() {}

...

try {
  m3();
} catch (Exception e) {}

W przypadku metody m3 łapany jest wyjątek typu Exception, który jest bazową klasą zarówno dla wyjątków Checked, jak i Unchecked (zwanych także runtime exceptions). Potencjał rzucenia wyjątku rodzaju Unchecked przez metodę m3 nie musi być deklarowany, ale może być obsłużony przez instrukcję try z klauzulą catch definiującą Exception jako łapany wyjątek, ponieważ wszystkie wyjątki rodzaju Unchecked dziedziczą po klasie Exception. Dlatego kod w tym przypadku kompiluje się bez błędów. W przypadku metody m2 kompilator zgłasza błąd, bo łapanie własnego wyjątku, który jest rodzaju Checked, nie daje takiej możliwości.

W moim kursie Nauka programowania w języku Java znajdziesz rozdział dedykowany wyjątkom, z których dowiesz się najważniejszych informacji o ich używaniu:

Nauka programowania w języku Java – Wyjątki

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Nie musisz podawać swojego imienia, e-mailu, ani strony www, aby opublikować komentarz. Komentarze muszą zostać zatwierdzone, aby były widoczne na stronie.