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