Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
1
Programowanie obiektowe w Javie
Paradygmaty i języki programowania Łukasz Kapral Andrzej Krupa Grzegorz Maślak Jakub Orłowski 17 marca 2013
2
Klasy i obiekty
3
Programowanie obiektowe
Programowanie obiektowe (ang. object-oriented programming) — paradygmat programowania, w którym programy definiuje się za pomocą obiektów — elementów łączących stan (czyli dane, nazywane najczęściej polami) i zachowanie (czyli procedury, tu: metody). Obiektowy program komputerowy wyrażony jest jako zbiór takich obiektów, komunikujących się pomiędzy sobą w celu wykonywania zadań.
4
Cechy obiektowego języka programowania
Dziedziczenie - polega na przypisywaniu tworzonej klasie wszystkich cech i zachowań klasy istniejącej Abstrakcja - każdy obiekt w systemie służy jako model abstrakcyjnego "wykonawcy", który może wykonywać pracę, opisywać i zmieniać swój stan, oraz komunikować się z innymi obiektami w systemie, bez ujawniania, w jaki sposób zaprogramowano dane cechy
5
Cechy obiektowego języka programowania
Polimorfizm (wielopostaciowość) – dla jednej metody określonej przez wspólny nagłówek istnieje wiele postaci treści tej metody Enkapsulacja (hermetyzacja) - zapewnia, że obiekt nie może zmieniać stanu wewnętrznego innych obiektów w nieoczekiwany sposób
6
Klasa Klasa - abstrakcyjny byt określający zbiór obiektów o takich samych właściwościach. Klasa definiuje zestaw pól i metod dla swoich obiektów. Przykładem klasy może być samochód. Może on podejmować różne działania np. jechać i ma pewne właściwości np. kolor. Jest jednak abstrakcyjny, mówiąc inaczej "nienamacalny". Jeżeli mówimy o klasie Samochód to oznacza, że mówimy o jakimś samochodzie.
7
Definicja klasy przyjmuje następującą formę:
[modyfikatory] class NazwaKlasy [extends NazwaNadklasy] [implements NazwyInterfejsów] { // Ciało klasy: // Tutaj znajdują się definicje pól danych, metod // i klas wewnętrznych klasy }
8
Przykładowe modyfikatory klas
Abstract Final Public Protected Private Static
9
Definicja pola klasy przyjmuje następującą formę:
modyfikatoryPola TypPola NazwaPola; Gdzie: modyfikatoryPola określają tryb dostępu (np. private) i właściwości pola (np. pole statyczne) TypPola specyfikuje typ pola danych; NazwaPola określa nazwę deklarowanego pola.
10
Definicja metody przyjmuje następującą formę:
modyfikatory TypRezultatu NazwaMetody(ListaParametrów) { //treść metody } Gdzie: modyfikatory określają tryb dostępu i właściwości metody TypRezultatu określa typ wyniku metody NazwaMetody która musi być poprawnym identyfikatorem Javy ListaParametrów lista argumentów przekazywanych do metody
11
Przykładowa klasa class Osoba { String imie; int wiek;
String imie(){ return imie; } void wiek(){ System.out.println("Masz " + wiek+ " lat"); } }
12
Przeciążanie metod Możemy przeciążać (ang. function overloading) nazwę metody, tzn. możemy stosować tę samą nazwę dla różnych metod, byleby tylko różniły się one między sobą liczbą lub rodzajem argumentów lub były metodami różnych klas.
13
Przykład void MojaMetoda() { ... }
void MojaMetoda(int i, String s) { ... } void MojaMetoda(String s) { ... }
14
Konstruktor metoda klasy wykonywana w momencie inicjalizacji obiektu tej klasy musi posiadać nazwę identyczną z nazwą klasy nie posiada typu zwracanego jeśli sami nie zdefiniujemy żadnego konstruktora, to kompilator sam wygeneruje bezargumentowy konstruktor domyślny
15
Przykład konstruktora
class Osoba { String imie; String nazwisko; Osoba(String imie, String nazwisko){ this.imie = imie; this.nazwisko = nazwisko; } Osoba() {this.imie = "nieznane"; this.nazwisko = "nieznane";}
16
Przykład konstruktora kopiującego
class Osoba { String imie; String nazwisko; Osoba(Osoba os) this.imie = os.imie; this.nazwisko = os.nazwisko; }
17
Finalizator W niektórych językach z wbudowanym odśmiecaczem (np. Java i C#) dostępna jest składnia finalizatora - specjalnej metody wywoływanej, gdy obiekt jest usuwany przy odśmiecaniu. W przeciwieństwie do destruktora nie wiadomo, w którym dokładnie momencie działania programu to nastąpi. Dodatkowo np. w Javie nie ma pewności czy metoda finalize() w ogóle zostanie wywołana.
18
Obiekt Obiekt - byt fizyczny stanowiący instancję klasy. O obiektach możemy myśleć jak o egzemplarzach określonych klas. Jeżeli mówimy o obiekcie samochód będącym instancją klasy Samochód to oznacza, że mówimy o konkretnym samochodzie.
19
Deklaracja zmiennej typu obiektowego:
NazwaTypu NazwaZmiennej [ = WartośćPoczątkowa ]; Przykład: Osoba os = new Osoba();
20
Notacja kropkowa Dostęp do atrybutów obiektu, reprezentowanych przez zmienną obiektową, realizujemy za pomocą wyrażeń kropkowych postaci: NazwaZmiennejObiektowej.NazwaAtrybutu; Przykład: os.imie = ”Jan”;
21
Czy wszystko w Javie jest obiektem?
Niemal wszystkie dane w Javie (poza kilkoma typami prostymi) traktowane są jako obiekty. Warto zaznaczyć, że od wersji 1.5 Java oferuje mechanizm "pudełkowania" (autoboxing) dla typów prostych. Wszelkie typy proste są w procesie kompilacji zamieniane na odpowiadające im obiekty. Mechanizm zamieniający kompilatora dba jednak o to, żeby skompilowany kod zachował zgodność wstecz. Obiekty odpowiadające typom prostym mogą zostać "wypakowane" (unboxing) do typu prostego.
22
Klasy osłonowe Boolean – boolean Character – char Integer – int
Double – double Float – float Byte – byte Short – short Long – long
23
Modyfikatory dostępu: public, private, package
24
Modyfikatory dostępu: public, private, protected, package
Cztery poziomy dostępu: Public Protected Default Private W języku java zgodnie z zasadami hermetyzacji języków zorientowanych obiektowo istnieje możliwość kontrolowania praw dostępu do klas oraz ich atrybutów i metod. Wyróżniamy 4 poziomy kontroli dostępu: -publiczny oznaczany słowem kluczowy public -chroniony oznaczany słowem kluczowy protected -domyślny zwany też pakietowym lub przyjaznym oznaczany przez brak słowa kluczowego -oraz prywatny oznaczany słowem kluczowy private
25
Modyfikatory dostępu Można stosować do: Klas Atrybutów Metod
Modyfikatory dostępu są słowami kluczowymi, które można zastosować przed następującymi definicjami: Klas w tym również klas wewnętrznych oraz klas zagnieżdżonych, a także typów wyliczeniowych i interfejsów. Atrybutów w tym również statycznych. Oraz metod w tym również metod statycznych i konstruktorów.
26
Modyfikatory dostępu: public
Źródło wywołania Dostęp Ta sama klasa Tak Klasa dziedzicząca w tym samym pakiecie Klasa niedziedzicząca w tym samym pakiecie Klasa dziedzicząca w innym pakiecie Klasa niedziedzicząca w innym pakiecie Modyfikator dostępu public oznacza, że każdy w każdej sytuacji ma pełny dostęp do elementu oznaczonego tym słowem kluczowym. Prawo zarówno do odczytu jak i zmiany wartości atrybutów, wywoływania metod jaki i tworzenia obiektów klas. Dodatkowo istnieją sytuacje, w których słowo to można pominąć, a element i tak będzie posiadał dostęp publiczny. Dzieje się tak podczas definicji atrybutów oraz metod w interfejsach. Również wartości typów wyliczeniowych są zawsze publiczne mimo, że nie jest to jawnie zdefiniowane.
27
Modyfikatory dostępu: default
Źródło wywołania Dostęp Ta sama klasa Tak Klasa dziedzicząca w tym samym pakiecie Klasa niedziedzicząca w tym samym pakiecie Klasa dziedzicząca w innym pakiecie Nie Klasa niedziedzicząca w innym pakiecie Jeśli pomijamy podczas definiowania klas, metod i atrybutów modyfikator dostępu, czyli nie używamy żadnego ze słów public, protected, czy private oznacza to, że wybraliśmy dostęp pakietowy. Oznacza to, że inne klasy z tego samego pakietu posiadają dostęp do zdefiniowanych elementów. Zaś klasy poza pakietem takiego dostępu nie posiadają. Dostęp pakietowy jest narzędziem służącym do organizacji kodu, pozwala on na grupowanie spokrewnionych klas w jednostki logiczne, czyli pakiety. Programista umieszczając klasy w jednym pakiecie daje im możliwość wzajemnego wpływania na elementy z dostępem pakietowym. Jest to najbliższy możliwy odpowiednik w języku java do oznaczania elementów jako ze sobą zaprzyjaźnionych. Najczęstszym wykorzystaniem w świecie javy dostępu pakietowego jest scenariusz, w którym w tym samym pakiecie znajdują się klasy oraz testy jednostkowe dla tych klas przeznaczone. Dzięki dostępowi pakietowemu testy mogą sprawdzać poprawność funkcjonalności ukrytych przed dostępem publicznym. W javie jeśli nie przyporządkujemy klasy do żadnego pakietu, a znajduje się one w tym samym folderze, trafiają do tak zwanego pakietu domyślnego i mają wzajemny dostęp do swych elementów z dostępem domyślnym.
28
Modyfikatory dostępu: private
Źródło wywołania Dostęp Ta sama klasa Tak Klasa dziedzicząca w tym samym pakiecie Nie Klasa niedziedzicząca w tym samym pakiecie Klasa dziedzicząca w innym pakiecie Klasa niedziedzicząca w innym pakiecie Modyfikatory dostępu można wykorzystywać podczas definiowania klas. Jednakże klasy zdefinioweane bezpośrednio w pliku java tzn takie które nie są częścią innej klasy mogą posiadać jedynie dostęp pakietowy lub dostęp publiczny. Dodatkowo w pliku java tylko jedna klasa może mieć dostęp publiczny. Modyfikatory private i protected można wykorzystywać przy definicjach klas wewnętrznych lub zagnieżdżonych, ale nie w tzw. Top level class. Dostęp prywatny oznacza, że do składnika klasy nie ma dostępu nikt poza jego własną klasą, z wnętrza jej metod. Słowo to jest bardzo przydatne w oznaczeniu, które składowe klasy powinny być ukrywane przed jej klientami. Np. ukrywamy dane klasy w zamian dostarczając publiczne metody, które na tych danych operują. Umożliwia to nam kontrole stanu obiektów, uniemożliwienie doprowadzenie obiektu do nielegalnego stanu jaki i możliwość stosunkowo swobodnej zmiany implementacji przechowywania danych bez wiedzy Klientów.
29
Modyfikatory dostępu: protected
Źródło wywołania Dostęp Ta sama klasa Tak Klasa dziedzicząca w tym samym pakiecie Klasa niedziedzicząca w tym samym pakiecie Klasa dziedzicząca w innym pakiecie Klasa niedziedzicząca w innym pakiecie Nie Dostęp protected jest nierozerwalnie połączony z koncepcją dziedziczenia. Powoduje ona, że komponenty klas oznaczone jako protected są publiczne dla klas, które po niej dziedziczą i prywatne dla wszystkich innych.
30
Modyfikatory dostępu: protected
Private Default Protected Public Ta sama klasa Tak Klasa dziedzicząca w tym samym pakiecie Klasa niedziedzicząca w tym samym pakiecie Klasa dziedzicząca w innym pakiecie Klasa niedziedzicząca w innym pakiecie Nie
31
Dziedziczenie, polimorfizm, hermetyzacja i klasy wewnętrzne
32
Dziedziczenie Dziedziczenie polega na przejęciu właściwości i funkcjonalności obiektów innej klasy i ewentualnej modyfikacji tych właściwości i funkcjonalności w taki sposób, by były one bardziej wyspecjalizowane. Dziedziczenie pozwala na zmniejszanie nakładów na kodowanie (reusing).
33
Dziedziczenie w Javie W Javie można dziedziczyć zarówno po klasach jak i po interfejsach. Oba te sposoby dziedziczenia są w Javie odmiennie wyrażane składniowo. Przy dziedziczeniu po klasach używa się słowa kluczowego extends, zaś przy dziedziczeniu po interfejsach słowa implements. Stąd często zamiast mówić o dziedziczeniu mówi się w Javie o rozszerzaniu klas lub implementowaniu interfejsów. Ponadto w Javie dziedziczenie po klasach jest ograniczone do tylko jednej bezpośredniej nadklasy (nie ma w Javie wielodziedziczenia takiego jak np. w C++), można natomiast dziedziczyć (bezpośrednio) po dowolnej liczbie interfejsów.
34
Przykłady // dziedziczenie po klasie class Pracownik extends Osoba{}
// dziedziczenie po kilku interfesjach class Samochód implements Pojazd, Towar{} // dziedziczenie po klasie i kilku interfejsach class Chomik extends Ssak implements Puchate, DoGłaskania{}
35
Przykłady cd. class Pracownik{ String imie; String nazwisko;
int wyplata; public Pracownik(String i, String n, int w){ imie = i; nazwisko = n; wyplata = w; } class Szef extends Pracownik{ int premia;
36
Uwaga Taki zapis: class Pracownik{} Jest równoznaczny z poniższym:
Jeśli klauzula extends jest pominięta, to domyślnie przyjmuje się, że klasa dziedziczy po klasie Object. Co za tym idzie każda klasa pośrednio lub bezpośrednio dziedziczy z klasy Object. Taki zapis: class Pracownik{} Jest równoznaczny z poniższym: class Pracownik extends Object{}
37
Dziedziczenie interfejsu
Podobnie jak klasy, tak i interfejsy mogą podlegać dziedziczeniu. Jednak dziedziczenie interfejsów jest bardziej rozbudowane, a mianowicie w procesie tym nie występuje ograniczenie co do jednokrotnego dziedziczenia. Interfejs może więc dziedziczyć po większej liczbie interfejsów.
38
Przykład interface Interfejs1 { void metoda1(int i); }
interface Interfejs3 extends Interfejs1, Interfejs2 { void metoda3(int i);
39
Przesłanianie metod Przesłanianie metod polega na tym że metoda podklasy ma tą samą nazwę i typ jak metoda nadklasy, wtedy mówimy że przesłania ją. Wersja metody dla nadklasy zostaje ukryta. Jeżeli z podklasy chcemy wywołać przesłoniętą metodę z nadklasy musimy poprzedzić ją przedrostkiem super.
40
Przesłanianie metod – wymagane warunki
typy wyników tych metod muszą być takie same lub kowariantne (co oznacza m.in., że typ wyniku metody z podklasy może być podtypem wyniku metody nadklasy) przedefiniowanie nie może ograniczać dostępu tzn. specyfikator dostępu metody przedefiniowanej w podklasie musi być taki sam lub szerszy (np. public zamiast protected) niż metody przedefiniowywanej metoda przedefiniowana (z podklasy) nie może zgłaszać więcej lub bardziej ogólnych wyjątków kontrolowanych niż metoda przedefiniowywana (z nadklasy)
41
Override Przedefiniowując metody w podklasach warto używać adnotacji @Override. Daje ona sygnał kompilatorowi, że intencją programisty jest przedefiniowanie metody. Na przykład, programista chce przedefiniować metodę getPreferredSize() z klasy Component w jakiejś jej podklasie, ale pomylił się w pisowni i zapisał metodę getPrefferedSize(). Nie ma błędu - to jest po prostu całkiem nowa metoda. Metoda getPreferredSize() używana jest przy wyznaczaniu preferowanych rozmiarów komponentu - programista chciał przedefiniować jej działanie z nadklasy. Program się skompiluje i będzie działał, ale kod metody napisanej przez programistę nie będzie wykonywany i trudno będzie dociec błędu. Jeśli użyjemy kompilator wykryje błąd i poinformuje o nim.
42
Przesłonięcie metody - przykład
class Pracownik{ String imie; String nazwisko; int wyplata; public void Zarabiam(){ System.out.println("Zarabiam " + wyplata); } class Szef extends Pracownik{ int premia; @Override super.Zarabiam(); System.out.println("Dostaję premię " + premia);
43
Metody finalne Ponieważ w Javie wszystkie metody są domyślnie wirtualne, implementacja każdej z nich może zostać podana lub zmieniona w klasach pochodnych. W celu zablokowania takiej możliwości należy metodę zadeklarować jako finalną. Oznacza to, że nie może ona zostać zaimplementowana w klasie pochodnej, a jej implementacja musi zostać podana w klasie w której została zadeklarowana. Przykład: public class Przyklad{ public final void metodaFinalna(){...} }
44
Klasy finalne Zadeklarowanie klasy jako finalnej oznacza, że nie może być ona dziedziczona przez inne klasy co może być podyktowane względami bezpieczeństwa lub efektywności. Wiele standardowych klas Javy jest klasami finalnymi np.: java.lang.System i java.lang.String. Wszystkie metody w klasie finalnej są automatycznie finalne. Np. klasa String jest definiowana jako: public final class String { ... }
45
Polimorfizm (wielopostaciowość)
Technika programowania obiektowego pozwalająca na tworzenie w hierarchiach klas wielu funkcji (metod) o takiej samej nazwie, ale różniących się implementacjami. W różnych klasach hierarchii może występować inna wersja takiej funkcji, która jest dostosowana do konkretnych potrzeb danego typu.
46
Przykład class Zwierze{
void DajGlos() { System.out.println("Zwierze"); } } class Pies extends Zwierze{ void DajGlos() { System.out.println("Pies"); }
47
Przykład cd. //wnętrze funkcji main Zwierze z = new Zwierze();
Pies p = new Pies(); z.DajGlos(); //wypisze "Zwierze" p.DajGlos(); //wypisze "Pies" z = p; z.DajGlos(); //wypisze "Pies"
48
Metody wirtualne Metody wirtualne to takie metody, dla których wiązanie odwołań z kodem programu następuje w fazie wykonania programu. W Javie wszystkie metody są wirtualne za wyjątkiem: metod statycznych (bo nie dotyczą obiektów, a klasy) metod deklarowanych ze specyfikatorem final, który oznacza, że metoda jest ostateczna i nie może być przedefiniowana metod prywatnych (bo metody prywatne nie mogą zostać przedefiniowane)
49
Klasy wewnętrzne Klasa wewnętrzna lub zagnieżdżona to klasa, która jest zdefiniowana wewnątrz innej klasy. Klasy wewnętrzne posiadają dostęp do metod statycznych klasy głównej, lecz nie muszą być instancjonowane wraz z nią.
50
Przykład class A { class B { } }
51
Hermetyzacja Hermetyzacja (enkapsulacja) – polega na ukrywaniu pewnych danych składowych lub metod obiektów danej klasy tak, aby były one dostępne tylko metodom wewnętrznym danej klasy lub funkcjom zaprzyjaźnionym. Gdy dostęp do wszystkich pól danej klasy jest możliwy wyłącznie poprzez metody, lub inaczej mówiąc: gdy wszystkie pola w klasie znajdują się w sekcji prywatnej lub chronionej, to taką hermetyzację nazywa się hermetyzacją pełną.
52
Hermetyzacja Trzy główne zalety hermetyzacji:
uodparnia tworzony model na błędy lepiej oddaje rzeczywistość umożliwia rozbicie modelu na mniejsze elementy
53
Przykład public class Foo { private int value = 666;
public void setValue(int newValue) { value = newValue; } public int getValue() { return value; } }
54
Klasy abstrakcyjne i interfejsy
55
Klasy abstrakcyjne i interfejsy
interface Instrument{ void play(); } abstract class AbstractInstrument implements Instrument{ String sound; AbstractInstrument(String sound){this.sound=sound;} void play(){ System.out.print(sound); class Trabka extends AbstractInstrument{ Trabka(){super("tururu");} Język java udostępnia dwa środki umożliwiające oddzielenie interfejsu klasy od jej implementacji. Są to klasy abstrakcyjne oraz interfejsy. Na slajdzie widać przykładową definicję interfejsu o nazwie Instrument. Po środku widzimy zdefiniowaną klasą abstrakcyjną, która interfejs implementuje. Natomiast na samym dole widać klasę, która rozszerza klasę abstrakcyjną. Jaki widać Java wspiera te mechanizmy interfejsów i klas abstrakcyjnych w sposób bezpośredni przy użyciu słów kluczowych. Jeśli chcemy by klasa została interfejsem używamy słowa kluczowego interface, jeśli chcemy by była klasą abstrakcyjną dodajemy słowo kluczowe „abstract” przed definicją klasy. Warto zauważyć, że takie podejście nie jest wcale powszechne. W wielu językach nawet w tych zorientowanych obiektowo, żeby daleko nie szukać na np. w C++, mechanizmy te są obecne tylko pośrednio, nie są elementem składni języka, a jedynie efektem końcowym kompilacji.
56
Klasy abstrakcyjne i interfejsy
Klasa abstrakcyjna: Nie da się utworzyć instancji Może zawierać metody abstrakcyjne Może zawierać metody Może zawierać atrybuty Może zawierać konstruktory Może zawierać klasy Jeśli deklarujemy klasę jako abstrakcyjną wiąże się to z następującymi rzeczami: Po pierwsze nigdy nie będzie możliwe stworzenie obiektu tej klasy. Kiedy oznaczamy klasę jako abstrakcyjną dajemy kompilatorowi do zrozumienia, że definicja tej klasy jest definicją niepełną, czegoś w niej jeszcze brakuje. Brakujące elementy powinny zostać zdefiniowane przez klasy, które po tej klasie abstrakcyjnej dziedziczą. Skoro klasa ta jest wybrakowana nie może zostać utworzona. Jednakże trzeba pamiętać, że każda klasa potomna pozostaje z naszą klasą abstrakcyjną w relacji „IS A” – czyli klasa potomna jest typu klasy abstrakcyjnej np. Trąbka jest abstrakcyjnym Instrumentem z poprzedniego przykładu. Czyli mimo, że nie jesteśmy w stanie stworzyć obiektu klasy abstrakcyjnej to możemy odwoływać się do obiektów klas potomnych, tak jakby były obiektami klasy abstrakcyjnej. Klasa abstrakcyjna może, ale nie musi zawierać w sobie metody abstrakcyjne. Oznacza to, że możemy stworzyć w pełni kompletną klasę, oznaczyć ją jako abstrakcyjną i uniemożliwić stworzenie jej instancji (obiektu). Z drugiej strony jeśli jakakolwiek metoda w klasie zostanie uznana za abstrakcyjną to klasa również musi zostać uznana za abstrakcyjną inaczej dostaniemy błąd kompilacji. Klasa abstrakcyjna jest poza tym normalną klasą jak każda inna. Co za tym idzie może zawierać metody, atrybuty, stałe, obiekty agregowane, klasy wewnętrzne i zagnieżdżone itd. Co bardziej zaskakujące klasy abstrakcyjne mogą zawierać również konstruktory, mimo że nie mogą zostać stworzone. Konstruktory takie mogą być wywoływane jedynie z klas bazowych.
57
Klasy abstrakcyjne i interfejsy
Interface: Nie da się utworzyć instancji Może zawierać deklaracje metod Może zawierać stałe Może zawierać klasy Klasa abstrakcyjna była dość podobna do zwykłej klasy można było dodać do niej zdefiniowane metody, atrybuty, konstruktory. Stanowiła pewną hybrydę pomiędzy interfejsem, a implementacją. Natomiast interfejs w javie związany jest wyłącznie z koncepcją interfejsu tzn. zwiera on kontrakt jaki musi być spełniony przez klasy pochodne, żeby te mogły zostać uznane za klasy pochodne. Przykładowo weźmy interfejs krzesło, definiuje on metodę „usiądź” jeśli chcemy by nasz obiekt rakietowego wózka ze zdalnym sterowaniem został krzesłem to musi on posiadać zdefiniowaną metodą „usiądź”. Interfejs tak jak klasa abstrakcyjna również nie może być utworzony. Interfejs może posiadać deklaracje metod, czyli ich nazwę, listę parametrów, typ zwracany, rzucane wyjątki – całą sygnaturę bez ciała. Dodatkowo wszystkie metody będą publiczne oraz abstrakcyjne nawet jeśli sami nie dodamy tych informacji. Interfejs może mieć również zdefiniowane stałe, którym przypiszemy od razu wartość. Trzeba mieć na uwadze, że tak zdefiniowane atrybuty będą statyczne oraz finalne. Jeśli w interfejsie zdefiniujemy klasę wewnętrzną trzeba mieć na uwadze, że będzie ona statyczna nawet jeśli nie zostanie to jawnie zadeklarowane.
58
Klasy abstrakcyjne i interfejsy
Interface – dziedziczenie wielokrotne Klasy – dziedziczenie pojedyncze Interfejsy różnią się od innych klas również tym, że umożliwiają wielokrotne dziedziczenie. Na przykład klasa trąbka może jednocześnie dziedziczyć interfejsy Instrument dęty oraz Instrument blaszany. W normalnych klasach takie zachowanie jest niedozwolone, wynika to z tzw. Problemu diamentowego. Na slajdzie widać klasę C, która dziedziczy po klasie B oraz D które z kolei obie dziedziczą po klasie A. Struktura taka przypomina diament stąd nazwa problemu. Jeśli klasa A posiada pewną metodę np. rysuj, a klasy B oraz D nadpisują ją zachowanie tej metody, to z którego nadpisanego zachowania powinna korzystać klasa C? W jaki sposób dwukrotnie zainicjalizować klasę A tak by komponenty klasy B i D działały prawidłowo w klasie C? Są to pytanie nietrywialne i nie ma na nie jednoznacznie dobrych odpowiedzi. Dlatego też wielokrotne dziedziczenie w javie jest zabronione. Można dziedziczyć wielokrotnie jedynie interfejsy, które nie posiadają nieabstrakcyjnych metod wiec powodują żadnych problemów .
59
Typ wyliczeniowy Enum Czasami może zaistnieć potrzeba określenia wartości stałych, reprezentujących jedyne wartości, jakie może przyjmować zmienna. Taki zbiór dozwolonych wartości często określany jest terminem wyliczenie. Przed pojawieniem się wersji 5.0 Javy możliwości tworzenia wyliczeń w Javie były jedynie połowiczne. Jednak w Javie 5.0 zostały one znacznie rozbudowane.
60
Typ wyliczeniowy Enum Wyliczenie (ang. enumeration), zwane także typem wyliczeniowym, jest zbiorem symbolicznych stałych całkowitych określających wszystkie dopuszczalne wartości, jakie może przyjąć dana zmienna. Wyliczenia są częstym elementem programów. Typ wyliczeniowy definiuje się za pomocą słowa kluczowego enum, umieszczanego na początku instrukcji. Ogólną postać: Typ wyliczeniowy (enumeration) w najprostszej postaci przypomina zbiór stałych o określonych wartościach, przy czym identyfikator i wartość to jedno i to samo oznaczenie. Typ wyliczeniowy w Javie to rodzaj klasy, może być zatem definiowany przez pola, metody i konstruktor (prywatny, dostępny wewnątrz). enum <nazwa_wyliczenia> {lista_wyliczenia} <lista_zmiennych>;
61
Nazwa wyliczenia i zmienne typu wyliczeniowego
Zarówno nazwa_wyliczenia wyliczenia, jak i lista_zmiennych są opcjonalne, ale nie można ich pominąć jednocześnie. Podobnie jak w przypadku struktur, nazwa wyliczenia umożliwia deklarowanie zmiennych tego typu.
62
Nazwa wyliczenia i zmienne typu wyliczeniowego
public enum Czlonkowie { JAREK, JUREK, FILIP }; public Czlonkowie wybranyCzlonekZespolu; … If (wybranyCzlonekZespolu == Czlonkowie.JAREK) { // adresowane do Jarka } Wygląda jak bardzo prosta definicja klasy? Okazuje się, że wyliczenia są specjalnym rodzajem klas. W zaprezentowanym przykładzie tworzymy nowy typ wyliczeniowy o nazwie Czlonkowie. Zmienna wybranyCzlonekZespolu jest typu Czlonkowie i może przyjmować jedynie jedną z wartości „JAREK, JUREK, FILIP” ==Czlonkowie.JAREK – składnia pozwalająca odwołać się do elementu wyliczenia
63
Typ enum jest typem wyliczeniowym, literałem, który jest traktowany jak klasa specjalna zawierająca w swojej definicji wszystkie możliwe do stworzenia instancje, obiekty. enum Stany{ A, B} Typ enum wygląda bardzo podobnie jak w C/C++/C# lecz jest bardziej rozbudowany. Najprostsza wersja ma postać: enum Stany{A, B} Sam typ enum jest traktowany tak jak klasa i może być przetwarzany w ten sam sposób. Jest on porównywalny (Comparable) i serializowany (Serializable). Tworząc nowe wyliczenie, tworzymy nową klasę, która niejawnie dziedziczy po klasie java.lang.Enum. Można zadeklarować wyliczenie jako niezależną klasę i umieścić ją w osobnym pliku źródłowym. Można także zadeklarować ją jako składową innej klasy.
64
Enum pola i metody - pola
enum Wartosci { A, B; public String name; protected String value; private int number; } Typ enum w języku java pozwala, w przeciwieństwie do swoich odpowiedników z innych języków, definiować pola i metody dla każdej z wartości. Wynika to z "klasowej" charakterystyki enumów. Prawidłowym jest zatem zapis ukazany na slajdzie.
65
Metody własne enum static values() - zwraca tablicę zawierającą wszystkie obiekty enum. W naszym przypadku będą to A i B static valueOf(String) - zwraca wartość enuma, w postaci obiektu enum, dla klucza określonego jako String static valueOf(Class< T >, String) - zwraca wartość enuma, w postaci obiektu enum, dla klucza określonego jako String z klasy enumów T. Typ enum zawiera trzy metody. Każdy typ wyliczeniowy posiada wbudowaną metodę values(), która zazwyczaj jest używana w pętlach for.
66
Definiowanie metod enum Wartosci { A, B("enum B"); //...
public void metoda1(){ } protected void metoda2(){ private void metoda3(){ private Wartosci(){ private Wartosci(String s){ name = s; Enum jest traktowany jak klasa zatem może posiadać też metody. Metody definiuje się tak samo jak w przypadku zwykłych klas. Możemy zatem napisać (slajd). Należy zwrócić uwagę na dwie istotne rzeczy. Po pierwsze konstruktor może mieć albo modyfikator private albo nie mieć modyfikatora (package-private). Może on przyjmować parametry, ale nie można wywoływać go bezpośrednio (należy użyć do tego stałych zdefiniowanych w typie). W powyższym przykładzie napisanie Wartosci.B stworzy obiekt typu Wartości i przekaże do konstruktora String "enum B". Nie można natomiast napisać new Wartosci("jakis napis"). Po drugie metody mogą mieć dowolny modyfikator dostępu. Dostęp do nich realizowany jest tak samo jak w przypadku zwykłych obiektów. Konstruktor enuma nigdy nie może zostać wywołany jawnie, wywoływany jest automatycznie, kiedy definiowana jest wartość stała typu wyliczeniowego. Konstruktor może mieć większą ilość parametrów niż 1, można również przeciążać konstruktory, dokładnie tak, jak w zwykłych klasach.
67
Enum w pętlach i przełącznikach (switch)
void metoda1(){ metoda(Wartosci.A); } void metoda(Wartosci w){ switch (w) { case A: break; case B: Do tych czas omówiliśmy jak tworzy się enum oraz co można, a czego nie można zdefiniować w jego ramach. Jednak prawdziwa siła enumów leży nie w samym sposobie ich definiowania lecz w możliwościach ich wykorzystania. Typu wyliczeniowego można używać do tworzenia alternatywnych ścieżek wykonywania programu, wykorzystując do tego instrukcje if i switch. Warto także zauważyć, że wartości typu wyliczeniowego można porównywać przy użyciu operatora == lub .equals(). == .equals()
68
Enum w pętlach i przełącznikach (pętle)
for(Wartosci w : Wartosci.values()){ System.out.println(w.value); } Enumy mogą zostać też użyte do reprezentowania dobrze określonych (przeliczalnych), skończonych i uporządkowanych zbiorów, na przykład talii kart, układu planetarnego, czy układu okresowego. A jak pracujemy na zbiorach to zawsze spotykamy się z problemem wykonania jakiejś operacji na wszystkich elementach tego zbioru.
69
Stałe w Javie
70
Stałe w Javie Słowo kluczowe final: Przypisanie możliwe tylko raz
Zmienne prymitywne prawdziwie stałe Zmienne obiektowe stałe jedynie, gdy zapewniono programistycznie W języku java do tworzenia stałych służy słowo kluczowe „final”. Postawione ono przy definicji zmiennej powoduje, że wartość zmiennej musi być ustalona podczas definicji tzn., że od razu musimy wpisać jej wartość oraz, że wartość ta nie może ulec zmianie. Cechy te są zapewnione w czasie kompilacji i dowolny kod który próbowałby naruszyć przypisaną wartość będzie błędny. Gdy słowo final jest używane ze zmiennymi prymitywnymi takimi jak: int, char lub double wtedy zachowują się tak jak tego oczekujemy. Są prawdziwie stałe ich wartości nie da się zmienić, nadpisać, można je tylko odczytywać. Kiedy słowa tego używamy do zmiennych obiektowych sytuacja ma się nieco inaczej. Pamiętajmy, że zmienne obiektowe w javie są to zmienne referencyjne oznacza to, że każda zmienna, której przypisujemy jakiś nowy obiekt nie przechowuje tak naprawdę tego obiektu, a jedynie do niego dowiązanie, czyli właśnie referencje. Oznacza to że słowo kluczowe final dotyczy się nie samego obiektu, a wartości dowiązania w zmiennej referencyjnej. Czyli: Obiekt który należy do zmiennej finalnej można bez problemu zmieniać, natomiast wskazanie na który obiekt wskazuje zmienna jest stałe. Jeżeli chcemy żeby obiekt zmiennej też był stały musimy zapewnić to sami programistycznie tzn. obiekt nie może posiadać metod umożliwiających zmianę któregokolwiek z jego atrybutów po utworzeniu tego obiektu. O tak zaprojektowanym obiekcie mówimy, że jest immutable czyli niemodyfikowalny.
71
Pola i metody statyczne
72
Pola i metody statyczne
Słowo kluczowe static: Przynależność do klasy, nie do obiektu Współdzielenie między wszystkimi instancjami Inicjalizacja podczas załadowania klas Brak polimorfizmu w metodach Używając słowa kluczowego static przed definicją atrybutu lub metody zmieniamy ich przynależność z przynależności do konkretnego obiektu na przynależność do klas. Co to właściwie znaczy? W przypadku atrybutów oznacza to, że obiekty nie posiadają atrybutu, który może mieć różne wartości niezależnie od instancji. Czyli obiekt A i obiekt B nie mogą posiadać atrybutu „dane”, który dla obiektu A i obiektu B będzie miał inna wartość. Zamiast tego tworzone jest pole którego wartość współdzielona jest między wszystkimi obiektami klasy. Każdy obiekt może go odczytywać i go zapisywać. Co więcej jeśli jeden obiekt go zmieni to wszystkie inne będą widziały tą zmianę. Statyczność pola w języku java gwarantuje nam, że pole to zostanie zainicjalizowane tylko raz. Istnieją przypadki w których nie możemy dopuścić żeby jakiś obiekt został stworzony więcej niż raz. Na przykład gdy mamy zasoby, które nie mogą być współdzielone. Użycie pola statycznego gwarantuje nam, że inicjalizacja obiektów zostanie wykonany tylko raz podczas ładowania klasy przez mechanizm „class loadera” w języku java stanie się to podczas pierwszego wykorzystania klasy przez program. Funkcje oznaczone jako statyczne nie należą do obiektów, a do klasy. Oznacza to że możemy je wywoływać nie posiadając ani jednego utworzonego obiektu, wystarczy nam nazwa klasy. Co za tym idzie metody statyczne nie mogą korzystać z atrybutów, które nie są statyczne, ponieważ te tworzone są dopiero wraz z tworzeniem obiektu. Skoro metody są częścią klasy a nie obiektów, oznacza to, że nie są wpisywane do tablicy funkcji wirtualnych. Skoro tak tzn., że funkcja statyczna nie może brać udziału w mechanizmach polimorfizmu. Czyli funkcji statycznej nie da się nadpisać.
73
Dokumentacja klas w javadoc
O co chodzi? Podczas tworzenia oprogramowania zachodzi potrzeba pisania różnego rodzaju dokumentacji technicznej. W językach obiektowych programy są zbiorami komunikujących się obiektów. Jedną z zalet tego modelu programistycznego jest możliwość powtórnego użycia obiektów w różnych programach. Jednakże gdy chce się powtórnie użyć obiekty, ważne jest by były one przejrzyście i jednolicie udokumentowane. Jednym z rodzajów dokumentacji technicznej jest tworzona właśnie po to, tak zwana dokumentacja API (Application Programming Interface) - interfejsu programisty, zawierająca opisy klas, klas wewnętrznych, interfejsów, konstruktorów, metod i pól. Javadoc jest narzędziem, które potafi wygenerować dokumentację HTMLową a podstawie komentarzy zamieszczonych w plikach z kodem źródłowym. Aby to było możliwe komentarze te muszą zostać odpowiednio sformatowane. Koncepcja działania Javadoc Javadoc do wykonania swojej pracy wymaga i bazuje na kompilatorze Javy. Pierwszą rzeczą, którą wykonuje program jest wywołanie części kompilatora javac do kompilacji kodu, zachowując deklaracje i komentarze do dokumentacji, lecz pomijając implementacje. Następnie buduje drzewo parsowania i z niego generuje odpowiednią dokumentację.
74
Wprowadzenie do Javadoc
standardowe narzędzie do tworzenia dokumentacji API dla Javy powstał w firmie Sun Microsystems jako część pakietu do tworzenia aplikacji Java 2 SDK służy tylko do dokumentowania programów napisanych w Javie generuje dokumentację z kodu źródłowego do formatu html Javadoc jest narzędziem, które parsuje deklaracje i komentarze dokumentacyjne w zbiorze plików zródłowych Javy i tworzy wyżej wspomnianą dokumnetację API w postaci zbioru stron HTML. Javadoc powstał w firmie Sun Microsystems i jest częścią pakietu do tworzenia aplikacji w języku Java - Java 2 SDK. Obecnie Javadoc jest de facto standardowym narzędziem do tworzenia dokumentacji API dla języka Java.
75
Co wygeneruje Javadoc? listę wszystkich pakietów w projekcie wraz z listą klas w każdym pakiecie hierarchię klas oraz zależności między klasami opis klasy, pakietu, projektu informacje o przestarzałych metodach (deprecated) alfabetyczny indeks klas, interfejsów, konstruktorów, pól i metod
76
Przykład wygenerowanej dokumentacji
77
Przykład wygenerowanej dokumentacji
78
Zasady działania Javadoc
bazuje na kompilatorze Javy używa specjalnych znaczników umieszczonych w komentarzach do generowania dokumentacji używa tzw. docletów do generowania plików wyjściowych (do określenia formatu wyjściowego)
79
Doclety programy napisane w Javie z własnym API określają zawartość i format pliku wyjściowego, wygenerowanego przez Javadoc aby użyć niestandardowego docletu: javadoc -doclet JP.co.esm.caddies.doclets.UMLDoclet -private *.java (UMLDoclet, generuje strony HTML zawierające diagramy klas w standardzie UML) np. można napisać doclet do generowania dowolnego pliku tekstowego firma Sun dostarcza standardowy doclet do generowania dokumentacji w formacie html oraz eksperymentalny – w formatach: MIF, PDF, PS, RTF, FrameMaker i innych.
80
Doclety szkielet docletu:
klasa RootDoc przechowuje informacje z jednego uruchomienia Javadoc (pakiety, klasy i opcje określone przez użytkownika) pliki z klasami API docletu są w pliku lib/tools.jar. Po kompilacji tools.jar musi być w ścieżce klasowej. można do tego celu użyć opcji -classpath z Javadoc.
81
Zalety Javadoc dokumentacja zintegrowana z kodem źródłowym
Zalety korzystania z Javadoc •problemem wielu programistów jest tworzenie dobrej dokumentacji do kodu zródłowego, •najwieksze kłopoty sprawia przechowywanie dokumentacji, •komentarz dokumentacyjny, którego uzywa się do tworzenia dokumentacji kodu moze zawierac opis klas i metod, ich argumentów, dziedziczenia, twórców kodu, wersji, itp. Dokumentacja znajduje się razem z kodem (powiazanie kodu z dokumentacja). Przy zmianie kodu, od razu zmienia się dokumentację. Javadoc może być używany w najwcześniejszych fazach projektowania, podczas specyfikacji API, bez gotowych implementacji. Od razu tworzone są 4 różne typy plików dokumentacji, co jest bardzo ważne w programowaniu obiektowym. Można tworzyć dokumentację w różnych formatach.
82
Wady Javadoc Javadoc nie wspiera innych języków niż Java
nie umożliwia dokumentowania treści metod generuje dokumentację tylko w formacie html Czego nie potrafi Javadoc? Javadoc nie potrafi: Tworzyć innej dokumentacji niż dokumentacja API. Tworzyć dokumentacji do innych języków niż Java Dokumentować treści metod
83
Znaczniki Javadoc @param nazwaParametru opis znacznik opisujący parametr klasy lub metody. W opisie powinien znaleźć się typ parametru. @return opis znacznik opisujący wartość zwracaną przez metodę. Opis powinien zawierać typ zwracanego wyniku oraz zakres zwracanych wartości. @throws wyjątek opis znacznik opsujący wyjątek, jaki może rzucić metoda. @author nazwa Informuje kto jest autorem kodu. Powinno być stosowane jedynie w opisie klas i interfejsów.
84
Znaczniki Javadoc @version textWersji znacznik informujący, do której wersji oprogramowania należy ta części kodu. @since textWersji znacznik informujący, w której wersji oprogramowania została dodana opisywana część kodu. @see odnosnik odnośnik do innych materiałów. Dopuszczalne są trzy formy: @see “napis” nie tworzy linku. Wyświetla tylko napis @see <a href="URL">etykieta</a> tworzy link do strony podanej jako URL @see pakiet.klasa#element etykieta najbardziej popularna forma. Tworzy odnośnik wewnątrz projektu do elementu klasy (metoda, pole).
85
Znaczniki Javadoc @deprecated opis znacznik informujący, że dana część kodu jest przestarzała i nie powinna być wykorzystywana. W opisie powinna wystąpić informacja od której wersji kod jest przestarzały oraz czym należy go zastąpić. pakiet.klasa#element etykieta} znacznik, który może wystąpić wewnątrz innego. Tworzy on odnośnik do elementu klasy i jest opatrzony etykietą.
86
Znaczniki Javadoc Gdzie jaki można stosować?
Znaczniki dokumentacji pakietu: @see @since @serial @author @version Wszystkie trzy rodzaje dokumentacji mogą zawierac który pozwala na odwołanie sie do dokumentacji innej klasy. Ponadto w dokumentacji klasy mozna zastosowac znaczniki: – autor kodu, – biezaca wersja kodu, – wersja kodu, która rozpoczyna stosowanie danej własnosci.
87
Znaczniki Javadoc Gdzie jaki można stosować?
Znaczniki dokumentacji klasy i interfejsu: @see @since @deprecated @serial @author @version
88
Znaczniki Javadoc Gdzie jaki można stosować?
Znaczniki dokumentacji pola: @see @since @deprecated @serial @serialField
89
Znaczniki Javadoc Gdzie jaki można stosować?
Znaczniki dokumentacji metod i konstruktorów @see @since @deprecated @param @return @throws @serialData – opis argumentu, – opis wartosci zwracanej, – kiedy zwracany jest dany wyjatek.
90
Znaczniki Javadoc Gdzie jaki można stosować?
Znaczniki dokumentacji metod i konstruktorów @see @since @deprecated @param @return @throws @serialData
91
Trzy rodzaje dokumentacji:
W komentarzach wystepuja trzy rodzaje dokumentacji: •dokumentacja klasy, •dokumentacja metody, •dokumentacja zmiennej (pola) Należy pamiętać, ze standardowo zostaną opisane tylko składowe klas oznaczane jako public i protected.
92
Jak korzystać z Javadoc?
Dokumentowanie klasy Dokumentowanie pola Dokumentowanie metody
93
menu Project -> Generate Javadoc
Javadoc w Eclipse szkielet komentarza można modyfikować: Window->Preferences->Java->Code Style->Code Templates. Eclipse umożliwia w łatwy sposób generowanie dokumentacji: menu Project -> Generate Javadoc
94
Uruchamianie Javadoc wyświetlenie instrukcji obsługi javadoc:
javadoc lub javadoc -help generowanie dokumentacji: javadoc [opcje] nazwa_pakietu lub javadoc [opcje] nazwa_pliku.java
95
Wyjątki w Javie Programista tworząc aplikację nie zawsze jest w stanie w pełni przewidzieć jej zachowanie, w szczególności gdy ma do czynienia ze zdarzeniami zależnymi od użytkownika, sieci, urządzenia zewnętrznego. Język Java umożliwia zabezpieczenie się przez błędami jakie mogą wystąpić podczas nieprzewidywanych zdarzeń. W przypadku wystąpienia błędu sterowanie programu wychodzi z aktualnie wykonywanej metody i przechodzi do specjalnego bloku obsługi wyjątku.
96
Wyjątki Java posiada zapożyczony z języka Ada mechanizm informowania o błędach: wyjątki (ang. exceptions). Mechanizm obsługi wyjątków w Javie umożliwia obsługę sytuacji krytycznych, dzięki czemu program nie zawiesi się po wystąpieniu błędu i wykona ciąg operacji obsługujących dany wyjątek. Mechanizm obsługi wyjątków zwiększa niezawodność programów Java. Wyjątek w Java jest obiektem, który opisuje sytuację błędną powstałą w kodzie. Zaistnienie sytuacji błędnej w metodzie powoduje utworzenie obiektu reprezentującego wyjątek i zgłoszenie go przez metodę, w której błąd wystąpił. Następnie metoda może sama obsłużyć wyjątek lub przesłać go do obsługi przez inne metody/obiekty. Wyjątki mogą być zgłaszane przez maszynę wirtualną Javy lub przez kod użytkownika. Wyjąki zgłaszane przez maszynę wirtualną są związane z tzw. błędami fatalnymi, natomiast zgłaszane przez użytkownika z błędami związamymi z logiką programu. Składnia programu obsługującego wyjątki bazuje na pięciu słowach kluczowych: try, catch, throw, throws i finally. Monitorowany kod znajduje się w bloku try. Zgłoszenie wyjątku wewnątrz bloku try powoduje powstanie obiektu-wyjątku i jego ewentualne przejęcie przez odpowiedni blok catch.
97
Wyjątki try { // zrób coś ryzykownego } catch (Exception ex) {
// spróbuj rozwiązać problem } Jak wcześniej wspomniałem, mechanizm obsługi wyjątków Javy jest eleganckim i dobrze udokumentowanym sposobem obsługi „sytuacji wyjątkowych” zachodzących podczas działania programu. Dodatkowo pozwala on na umieszczenie całego kodu służącego do obsługi wyjątków w jednym, łatwym do znalezienia miejscu. Mechanizm ten bazuje na wiedzy, że wywołana metoda jest ryzykowna (to znaczy, że może zgłosić wyjątek), dzięki czemu jesteśmy w stanie napisać kod, który obsłuży taką ewentualność. Co jest ważne? Wyjątek jest obiektem, a zatem to, co uzyskujemy w wyniku przechwycenia wyjątku, jest obiektem. // spróbuj rozwiązać problem – ten kod zostanie wykonany wyłącznie w przypadku, gdy zostanie zgłoszony wyjątek Exception. Kod jaki należy umieścić wewnątrz bloku catch, zależy od zgłoszonego wyjątku. Na przykład, jeśli serwer będzie niedostępny, to wewnątrz bloku catch można spróbować nawiązać połączenie z innym serwerem. Jeśli natomiast nie będzie potrzebnego pliku, można poprosić użytkownika aby pomógł go odszukać.
98
Wyjątki wyjątki kontrolowane (ang. checked exeptions) – stanowią większość wyjątków w Javie. Znaczy to, że kompilator jest w stanie sprawić, że każda metoda zgłasza tylko te wyjątki, które są jawnie wymienione w jej deklaracji. wyjątki niekontrolowane (ang. unchecked exeptions) – standardowe wyjątki i błędy zgłaszane przez system wykonawczy, które są podklasami klas RuntimeExeption i Error. Wszystkie wyjątki, na które kompilator zwraca uwagę, są nazywane wyjątkami sprawdzanymi (lub kontrolowanymi), co w rzeczywistości oznacza, że są to wyjątki sprawdzane przez kompilator. Jedynie wyjątki RuntimeException nie są sprawdzane. Wszystkie pozostałe wyjątki muszą zostać potwierdzone w kodzie, zgodnie z określonymi regułami.
99
Wyjątki klasy RuntimeException
Kompilator sprawdza wszystkie wyjątki za wyjątkiem wyjątków klasy RuntimeException RunTimeExceptions jest to szczególna podklasa klasy Exception. Obsługuje ona wyjątki, które występują podczas wykonywania programu. Występują one np. wtedy, gdy zostaną wyczerpane zasoby systemowe lub nastąpi odwołanie do nie istniejącego elementu tablicy lub pliku. Kompilator zwraca uwagę na wszystkie klasy potomne klasy Exception za wyjątkiem wyjątków specjalnego typu – RuntimeException – tak zwanych wjątków czasu wykonania programu. Każda klasa rozszerzająca RuntimeException ma „wolną drogę”. Wyjatki tego typu mogą być zgłaszane w dowolnym miejscu kodu i nie trzeba ich deklarować ani przechwytywać przy użyciu bloków try-catch. Wyjątki klasy RuntimeException NIE są sprawdzane przez kompilator. Są one nazywane „wyjątkami niesprawdzanymi”. Można zgłaszać, przechwytywać i deklarować wyjątki tego typu, jednak nie trzeba tego robić – kompilator i tak tego nie sprawdza. Czemu? Większość wyjątków tego typu jest spowodowanych problemami związanami z logiką działania kodu, a nie z warunkami, które nie są spełnione podczas wykonywania programu i to w taki sposób, którego nie jesteśmy w stanie przewidzieć.
100
Wyjątki Programista sam może decydować czy w danym momencie ma być „wyrzucany” wyjątek czy nie. Zasada: wyjątek jest wtedy gdy w danym momencie przetwarzania danych nie mamy wystarczająco wiedzy aby poradzić sobie z powstałym problemem.
101
Użyteczne metody klasy Throwable
String getMessage() - zwraca napis podany kontruktorowi wyjątku Exception. String toString() - zwraca napis reprezentujący nazwę wyjątku (klasy wyjątku). void printStackTrace() - wypisuje call stack trace czyli sekwencję metod, która została wywołana do momentu wyrzucenia wyjątku.
102
Deklarowanie typów wyjątków
Do opisu sytuacji wyjątkowych wygodnie jest mieć więcej danych niż tylko napis, który udostępnia klasa Exception. W razie potrzeby, możemy utworzyć podklasę klasy Exception, która będzie zawierała niezbędne dodatkowe dane. Przeanalizujmy sytuację dot. aplikacji „Egzamin”, w której będziemy potrzebowali zgłosić przykładowy wyjątek NieZdalEgzaminu. Zgłaszany wyjątek powinien zawierać informację: kto nie zdał egzaminu i z jakiego przedmiotu. Wyjątek zawsze jest obiektem klasy Exception (oznacza to, że jest obiektem klasy, w której drzewie dziedziczenia znajduje się klasa Exception).
103
Deklarowanie typów wyjątków
public class NieZdalEgzaminu extends Exeption{ public Student student; public String przedmiot; NieZdalEgzaminu(Student nieprzygotowany, String nazwaPrzedmiotu){ super("Student " + nieprzygotowany.nazwisko+ "nie zdal " + przedm); student=nieprzygotowany; przedmiot=nazwaPrzedmiotu; }
104
Wykorzystanie instrukcji throw i klauzuli throws (1)
Instrukcja throw – służy do zgłaszania wyjątków. Wymaga podania obiektu reprezentującego wątek. Klauzula throws – w jej treści opisywane są wyjątki kontrolowane przez daną metodę (lista nazw oddzielonych przecinkami). nazwaMetody(zmienne) throws Wyjątek1, Wyjątek2 { instrukcje; ... throw Wyjatek1; } Metoda zgłasza wyjątek przy użyciu słowa kluczowego thorw, po którym tworzony jest nowy obiekt wyjątku throw new NazwaException(); Metoda, która zgłosi wyjątek musi o tym poinformować przy użyciu deklaracji throws KlasaWyjatku
105
Wykorzystanie instrukcji throw i klauzuli throws (2)
public void przeprowadzEgzamin(Student student, String przedmiot) throws NieZdalEgzaminu { ... //instrukcje ... if(student.ocena==2) throw NieZdalEgzaminu(student, przedmiot); else student.wpiszDoIndexu(przedmiot, student.ocena); }
106
Wykorzystanie instrukcji try oraz klauzul catch i finally (1)
Wyjątki można wychwytywać za pomocą instrukcji try. Składnia bloku try jest następująca: try //instrukcje catch(typ_wyjatku id) ... finally
107
Wykorzystanie instrukcji try oraz klauzul catch i finally (2)
Instrukcje umieszczone w sekcji try są wykonywane do chwili zgłoszenia wyjątku. Jeśli zostanie zgłoszony wyjątek, to będą przeszukane kolejne klauzule catch w celu znalezienia klasy (lub superklasy) zgłoszonego wyjątku. Jeżeli klasy wyjątku nie uda się znaleźć, to wyjątek jest propagowany na zewnątrz instrukcji try. Fakultatywna klauzula finally będzie zawsze wykonana po wszystkich czynnościach związanych z obsługą klauzul catch.
108
Wykorzystanie instrukcji try oraz klauzul catch i finally (3)
przeprowadzEgzamin(ProgramowanieJava); } catch(NieZdalEgzaminu e){ System.out.println("Niestety, tym razem nie udało się."); } finally{ System.out.println("Dziękuję za interesującą wymianę zdań!");
109
Tworzenie własnych wyjątków
class Lapsus extends Exception{...} public class Test{ public void zaplanowaneDzialania() throws Lapsus{ //spodziewamy się powodzenia, ale... throw new Lapsus(); } public static void main(String[] args){ Test t = new Test(); try{ t.zaplanowaneDzialania(); } catch(Lapsus e){ System.err.println(„Przechwycony błąd!”); e.printStackTrace(); } }
110
Kiedy używać wyjątków? Wybór sytuacji, w których należy zgłosić wyjątek, nie podlega żadnym sztywnym regułom. Należy jednak pamiętać o tym, aby nie nadużywać wyjątków jako metody zgłaszania sytuacji normalnych i oczekiwanych.
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.