Błędy i Wyjątki Programy zawierają błędy im więcej linii kodu, tym prawdopodobieństwo wystąpienia błędu w kodzie jest większe. JTP: Wyjątki Typizacja pozwala na wykrycie części z nich, podobnie testowanie, ale nie wszystkich. Część błędów w kodzie zostaje ujawniona dopiero w czasie wykonania programu i wtedy trzeba coś z nim zrobić. Z drugiej strony, użytkownik może wywołać metodę w niewłaściwy sposób i też wymaga zaradzenia. Dr. Piotr Kosiuczenko W jawie rozróżnia się błędy (ang. Error) i wyjątki (ang. Exception). Oba są podklasami Throwable. 1 2 JTO JTP Dr Piotr Kosiuczenko Throwable Wyjątki Gdy coś jest nie tak, np. program próbuje przeczytać wartość Rzucenie obiektu z klasy Throwable sygnalizuje pewną atrybuty obiektu null, wtedy jest rzucany obiekt klasy anomalię. Throwable. Mechanizm wyjątków stosuje się do zaradzania pewnym Rzucenie takiego obiektu może prowadzić albo do przerwania sytuacjom. wykonania programu, albo może być odpowiednio potraktowane. Mechanizm błędów stosuje się do informowania o tym, ze try { . . . //execute method(); wystąpił błąd, z którego program nie może usunąć. } catch (ErrorOrException e) { . . . //do something about it } finally { . . . //do whatever } 3 4 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Throwable: Bledy i Wyjątki Wyjątki Throwable Exception Throwable (String message) ClassNotFound CloneNotSupported Runtime IOException Exception Exception Exception Error Exception MalFormed URLException Assertion IOError Error, czyli błąd, jest podklasą Error Throwable. Obiekty klasy Exception i jej podklas wskazują EOFException na warunki, które mogą być odpowiednio Błąd oznacza poważny problem. potraktowane. Błędy nie powinny być łapane. Interrupted Wtedy taki wyjątek jest łapany i odpowiednia IOException W rezultacie metoda rzucająca błąd nie procedura, jeśli jest przewidziana, zostaje musi deklarować go w klauzuli throws. wykonana. 5 6 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko 1 Sprawdzane Wyjątki Wyjątki Exception Wyjątki są mechanizmem przekazania kontroli i informacji z pewnego punktu w programie do kodu obsługi wyjątków. ClassNotFound CloneNotSupported RunTime IOException Exception Exception Exception try { . . . //execute method(); MalFormed } catch (ErrorOrException e) { URLException . . . //do something about it } finally { EOFException Są dwa rodzaje wyjątków: sprawdzane i nie . . . //do whatever (ang. checked i unchecked exceptions). } Sprawdzane wyjątki muszą być albo deklarowane Interrupted IOException w sygnaturze metody, albo łapane i obsługiwane wewnątrz niej. 7 8 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Wyjątki: Przykład Deklaracja Wyjątku Deklaracja wyjątku w Tu może być sygnaturze metody rzucony try { wyjątek. System.out.println( What s your name? ); public void ask() throws IOExceptio { String name = console.readLine(); System.out.println( What s your name? ); System.out.println( Hello, + name + ! ); String name = console.readLine(); } catch (IOException e) { System.out.println( Hello, + name + ! ); e.printStackTrace(); } Tu jest on Nie ma System.exit(1); łapany. klauzul try i } catch. IOExceptio musi być obsłużony przez metodę wywołującą lub A tu jest on zadeklarowany w jej sygnaturze. obsługiwany. 9 10 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Wyjątki Czasu Wykonania Deklaracja Wyjątku Deklaracja wyjątku Exception nie jest potrzebna. public void credit(int amount) { ClassNotFound CloneNotSupported Runtime IOException if(amount < 0) Exception Exception Exception throw new IllegalArgumentException( Over limit! ); balance = balance amount; } IllegalArgument Nie ma Exception Wiadomość o klauzul try i bledzie. catch. Wyjątki czasu wykonania nie muszą być IllegalState deklarowane w sygnaturze metody. Exception Ten wyjątek może być albo obsłużony przez metodę wywołującą, Jeśli jednak metoda może rzucić innego rodzaju albo przekazany dalej. IllegalState wyjątek, to ten wyjątek musi być zadeklarowany Exception w jej sygnaturze. 11 12 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko 2 Deklaracja Wyjątku Obsługa Wyjątków public void transfer(BankAccount target, double amount) { final double oldBalanceThis = this.balance; final double oldBalanceTarget = target.balance; public void transfer(BankAccount target, double amount) { try{ this.debit(amount); this.debit(amount); Zapisujemy wartość atrybutów. target.credit(amount); target.credit(amount); } catch (IllegalArgumentException e) { } Te instrukcje mogą Wykonujemy procedurę. this.balance = oldBalanceThis; rzucać wyjątki. Co z nimi zrobić? target.balance = oldBalanceTarget; W razie rzucenia } wyjątku przywracamy } wartość atrybutom Metoda wywołana przez inną metodę może rzucić wyjątek. Chcemy przywrócić stan sprzed rzucenia wyjątku. sprzed wykonania procedury. 13 14 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Finally Dziedziczenie: Co będzie wynikiem kompilacji? public class C { public class C { public void m() { try { . . . //execute method(); public void m() throws } IOException { } catch (ExceptionX e) { } } . . . //do something about it } } catch (ExceptionY e) { public class D extends C { . . . //do something about it public void m() throws IOException { public class D extends C { } finally { } public void m() { . . . //do whatever } } } } Będzie wykonana A tu jest on Wynikiem będzie pierwsza klauzula Jest wykonywane obsługiwany. komunikat o błędzie catch, która złapie niezależnie od tego, Wynikiem będzie powstanie kompilacji. czy wyjątek zostanie rzucony wyjątek. klas binarnych. rzucony. 15 16 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Pytanie: Co będzie wynikiem wykonania metody n? Wyjątki a Dziedziczenie public void m() { Podklasa musi zachowywać kontrakt nadklasy. W przypadku dziedziczenia metoda try { w podklasie może rzucać tylko takie sprawdzane wyjątki, które są deklarowane w System.out.println("m throws rune time exception e."); nadklasie. throw new RuntimeException(); } catch(RuntimeException e){ class Parent { System.out.println("m handles e."); public void m() throws IOException { throw e; //. . . } } finally{ } System.out.println("m executes its finally-part."); } class Child1 extends Parent { } public void m() { OK, nie rzuca //. . . sprawdzanych public void n() { } wyjątków. try { } System.out.println("n calls m."); OK, rzuca wyjątek będący m(); import java.io.IOException; szczególnym przypadkiem } catch(RuntimeException e){ class Child2 extends Parent { wyjątku w nadklasie. System.out.println("n handles e."); public void m() throws InterruptedIOException { } //. . . finally{ } System.out.println("n executes its finally-part."); } 17 } 18 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko } 3 Odpowiedz n calls m. m throws rune time exception e. m handles e. JTP: Klonowanie m executes its finally-part. n handles e. n executes its finally-part. Dr. Piotr Kosiuczenko 19 20 JTO JTP Dr Piotr Kosiuczenko Klonowanie Klonowanie clone() może być przedefiniowana w podklasach a jej dostępność Jeśli klasa implementuje interfejs Cloneable, to jest rozszerzona do publicznej: możliwe klonowanie za pomocą standardowej metody. public Object clone () throws CloneNotSupportedException { Klasa Object zawiera metodę protected Object return super.clone(); clone(). } Metoda ta zwraca wyjątek, jeśli obiekt, na którym została wykonana, należy do klasy, która nie implementuje lb interfejsu Cloneable. a1 : A b1 : B Jeśli obiekt należy do klasy implementującej Clonable, to metoda ta zwraca nowy obiekt, którego atrybuty są Co będzie wynikiem klonowania obiektu a1? identyczne z atrybutami klonowanego obiektu. Czasem głębsze klony są potrzebne. W przypadku tablicy i wektora zwracana/y jest nowa tablica/nowy wektor, których elementami są elementy klonowanej tablicy/wektora. 21 22 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Klonowanie Klonowanie Czasem głębsze klony są potrzebne: Co się stanie gdy metoda clone() zostanie wykonana w public class A implements Cloneable { następującym przypadku? private B b; public class Child extends Parent { public Object clone() throws public Object clone () throws CloneNotSupportedException { CloneNotSupportedException { A x = (A)this.clone(); Child x = (Child)super.clone(); if(this.b != null) } x.b = (B)b.clone(); } Rzucony zostanie return x; wyjątek, bo metoda } sklonuje this jako obiekt klasy Parent. } 23 25 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko 4 Identyczność: equals() Klasa Object zawiera metodę: public boolean equals(Object obj) Metoda ta służy do porównywania obiektów. JTP: Identyczność Porównywanie Obiektów W przypadku klasy Object porównywane są obiekty tak, jak w przypadku ==, tj. this.equals(Object o) zwraca true, jeśli this jest tym samym obiektem co o. W ogólności jednak metoda ta ma służyć do porównywania stanów obiektów, w szczególności ich atrybutów. Dr. Piotr Kosiuczenko 26 27 JTO JTP Dr Piotr Kosiuczenko Identyczność: equals Identyczność: Implementacja class Point { Metoda equals(Object o) powinna spełniać następujące public boolean equals(Point o) { warunki dla x i y różnych od null (porównaj Java API): przeładowanie uwaga return (this.x == o.x && this.y == o.y);na tę metodę, bo może zwrotność: x.equals(x) zwraca true. } być niespodziewanie //... symetria: x.equals(y) zwraca true wtw y.equals(x) użyta. } zwraca true. public boolean equals(Object o) { przechodniość: jeśli x.equals(y) zwraca true i jeśli if(!(o instanceof Point)) return false; y.equals(z) zwraca true, to x.equals(z) zwraca true. else return (this.x == ((Point)o).x && zgodność: wielokrotne wywołanie x.equals(y) stale zwraca this.y == ((Point)o).y); przedefiniowanie } true lub stale false. x.equals(null) zwraca false. Uwaga na dziedziczenie! 28 29 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Identycznosc: Impl. z Uwzgl. Dziedziczenia Identyczność: Implementacja z Uwzgl. Dziedziczenia public class ColourPoint extends Point { public class Point { int c; ... public ColourPoint(double nx, double ny, int nc) { public boolean equals(Object o) { ... if(!(this.getClass() == o.getClass())) } return false; public boolean equals(Object o) { else return (this.x == ((Point)o).x && if(!(o instanceof ColourPoint)) return false; this.y == ((Point)o).y); return (super.equals(o) && } this.c == ((ColourPoint)o).c); symetryczne warunki } } public static void main(String[] args) { public class ColourPoint extends Point { ColourPoint cp1 = new ColourPoint(1, 2, 7); ColourPoint cp2 = new ColourPoint(1, 2, 7); int c; Point p1 = new Point(1, 2); ... System.out.println(cp1.equals(cp2)); public boolean equals(Object o) { System.out.println(cp2.equals(cp1)); if(!(this.getClass() == o.getClass())) System.out.println(cp1.equals(p1)); return false; System.out.println(p1.equals(cp2)); Uwaga na else return (super.equals(o) && symetryczny warunek } przeładowanie. this.c == ((ColourPoint)o).c); } } Zobacz poprzedni } Niesymetryczna slajd. 30 31 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko relacja. 5 Identycznosc vs. Klonowanie Zasadniczo powinno być tak, że jeśli o1 jest klonem o2 dokonanym na tym samym poziomie co aktualna klasa o2, to o1.equals(o2) zwraca true. JTP: Rodzaje w Javie (Java Generics) (równoważnie o.equals(o.clone()) zwraca true) Co więcej: o.clone().getClass() == o.getClass(). Dr. Piotr Kosiuczenko 33 34 JTO JTP Dr Piotr Kosiuczenko Rodzaje Klasy Rodzajowe Rodzaje zapewniają bezpieczeństwo związane z typami. Niektóre typy danych i klasy mogą być zaimplementowane niezależnie od konkretnego typu swoich atrybutów i metod, tzn. W czasie kompilacji jest możliwość sprawdzenia poprawności mogą posiadać parametry będące typami (polimorfizm). danej formuły pod względem typów: Vector - kiedy taki parametr zostaje zastąpiony Vector v Vector; konkretnym typem, taka klasa może być skompilowana. Klasa posiada parametry, których wartościami są typy jest Vector v = new Vector(); nazywana parametryczną lub rodzajową. v.add(10); v.add( TEN");
35 36 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Klasy Rodzajowe Klasy Rodzajowe public class Pair { public String toString() { private T first; private T second; return "[" + first.toString() + ", " + public Pair(T f, T s) { Parametrem musi być second.toString() + "]"; first = f; klasa - nie może być second = s; } typ prymitywnym. Parametr musi } być klasą. public Pair() { Niepoprawna first = new T(); public boolean equals(Object o) { deklaracja second = new T(); } if(!(this.getClass() == o.getClass())) return public T getFirst() { false; return first; } return (this.first.equals(((Pair)o).first) && public T getSecond() { metoda this.second.equals(((Pair)o).second)); return second; parametryczna } } public void setFirst(T f) { Wiemy, że o jest tej } first = f; samej klasy, co this. } public void setSecond(T s) { second = s; 37 38 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko } 6 Dlaczego Klasy Rodzajowe? Dlaczego Klasy Rodzajowe? Impl. bez rodzajów static void swapAll(Collection c) { static void swap(Collection> c) { for (Object el : c) { for (Pair el : c) { T t = ((Pair)el).getFirst(); T t = el.getFirst(); ((Pair)el).setFirst(((Pair)el).getSecond()); el.setFirst(el.getSecond()); ((Pair)el).setSecond(t); el.setSecond(t); implementacja z musimy } } rodzajami dopasować typ } } Collection c = new Vector(); Collection c = new Vector>(); c.add(new Object()); c.add(new Object()); c.swapAll; c.swapAll; spowoduje błąd w czasie kompilacji spowoduje bląd w czasie wykonania 39 40 JTP Dr Piotr Kosiuczenko JTP Dr Piotr Kosiuczenko Konstruktory Konstruktory Niektóre typy danych i klasy mogą być zaimplementowane Czasem jest konieczne ograniczenie parametrów: niezależnie od konkretnego typu swoich atrybutów i metod, tzn. class RestrictedPair { mogą posiadać parametry będące typami. ... Pair