Dawid Gierszewski Adam Hanasko
Chcemy stworzyć klasę w której możemy przechowywać dwie zmienne dowolnych typów
Tworzymy tyle różnych klas ile potrzeba: Class ParaInt{ int pierwszy; Int drugi; Class ParaButow{ But pierwszy; But drugi; Redundancja kodu, wiele możliwości pomyłki
Stosujemy mechanizm dziedziczenia public class ParaObiektow { Object pierwszy; Object drugi; public Object getpierwszy() { return pierwszy; public static void main(string[] args) { ParaObiektow para = new ParaObiektow("tekst", new Integer(20)); String tekst = (String) para.getpierwszy(); Rezygnujemy z automatycznego sprawdzania typów wykonywanego przez kompilator i każemy mu uwierzyć (a nie wyliczyć), że typ obiektu jest właściwy.
Pomysł jest bardzo prosty - chcemy sparametryzować fragment kodu typem przetwarzanych danych, więc dodajemy nowy rodzaj parametrów opisujących typy. public class Para<T1, T2> { T1 pierwszy; T2 drugi; public Para(T1 pierwszy, T2 drugi) { this.pierwszy = pierwszy; this.drugi = drugi; public T1 getpierwszy() { return pierwszy;
Typem jest klasa uogólniona wraz z konkretnymi parametrami Pary z różnymi typami parametrów są różne Para< String, Integer> p1 = null; Para< Integer, String> p2 = p1; // błąd Jako parametrów typów uogólnionych nie można podawać typów prostych Para<int, int> para = new Para<int, int>(7, 13); // błąd Para<Integer, Integer> para = new Para<Integer, Integer>(7, 13);
zwykłe klasy mogą dziedziczyć po (ukonkretnionych) klasach uogólnionych public class ParaInt extends Para<Integer, Integer>{ public ParaInt(Integer pierwszy, Integer drugi){ super (pierwszy, drugi); klasy uogólnione mogą dziedziczyć po klasach uogólnionych public class ParaJednorodna<T> extends Para<T,T>{ public ParaJednorodna(T pierwszy, T drugi) { super (pierwszy, drugi); argumentami dla klas uogólnionych mogą być dowolnie złożone typy, w szczególności ukonkretnienia tych samych klas uogólnionych Para< Para<String, Integer>, String > dużapara
deklaracje poprzedzamy podaniem parametrów (w postaci listy ujętej w kątowe nawiasy) public class TestMetody { <T> Para<T,T> utworzpare(t v) { return new Para<T,T>(v, v); void test() { Para<Integer, Integer> p = utworzpare(new Integer(202));
Przykład chcemy sortować parę: public class ParaPosortowana <T> extends ParaJednorodna<T> { public ParaPosortowana(T pierwszy, T drugi) { super(pierwszy, drugi ); if (pierwszy().compareto(drugi()) > 0) // blad { T pom = pierwszy(); pierwszy(drugi()); drugi(pom); Powinno być: public class ParaPosortowana <T extends Comparable<T> > extends ParaJednorodna<T>
klasy, których obiekty służą do przechowywania zestawów innych obiektów udostępniają mechanizmy pozwalające na wstawianie, przeglądanie i pobieranie składowanych w nich obiektów mają służyć do przechowywania obiektów różnych typów kolekcja jest w stanie pomieścić w zasadzie dowolną ilość obiektów
Klasy konkretne Klasy abstrakcyjne Interfejsy
Metoda int size() boolean isempty() boolean contains(object o) boolean add(object o) boolean addall(collection c) boolean remove(object o) boolean removeall(collectin c) boolean retainall(collection) void clear() Object [] toarray() Opis zwraca liczbę elementów zawartych w kolekcji sprawdza, czy kolekcja jest pusta sprawdza, czy kolekcja zawiera podany obiekt. dodaje obiekt o do kolekcji. dodanie do dowolnej kolekcji wszystkich elementów kolekcji przekazanej przez parametr c usuwa obiekt o z kolekcji. usunięcie z kolekcji wszystkich elementów, które są zawarte w kolekcji przekazanej przez parametr c pozostawienie w kolekcji tylko tych elementów, które są zawarte w kolekcji przekazanej przez parametr c usunięcie wszystkich elementów kolekcji. zwraca tablicę obiektów zawartych w kolekcji.
Implementują metody z interfejsów AbstractCollection<E> implementacja większości metod zadeklarowanych w interfejsie Collection AbstractList<E>, AbstractQueue<E>, AbstractSet<E> dziedziczą po AbstractCollection i implementują większość metod interfejsów odpowiednio List, Queue, Set
ArrayList<E> realizacja tablicy dynamicznej dziedzicząca po AbstractList LinkedList<E> lista dziedzicząca po AbstractSequentialList TreeSet<E> zbiór przechowywany w strukturze typu drzewa HashMap<K,V> podstawowa implementacja interfejsu Map<K,V>. Zgodnie z nazwą stosuje w swojej implementacji haszowanie. Zapewnia dostęp do elementów (metody get i put) w czasie stałym (o ile funkcja haszująca równomiernie rozrzuci klucze).
Iterator to obiekt pozwalający poruszać się (iterować) po innym obiekcie (kolekcji). Interfejs Iterator<E> Przykład: Iterator iter = c.iterator(); metoda boolean hasnext(); E next(); while(iter.hasnext()) void remove(); { Object o = iter.next(); //... // wykonanie operacji na obiekcie o //... if ( warunek_usuniecia(o) ) iter.remove(); opis informuje, czy w kolekcji są jeszcze elementy pobiera kolejny element z kolekcji usuwa z kolekcji element, który był ostatnio przekazany jako wynik metody next.
Służy do wykonania operacji na wszystkich elementach for (Typ Identyfikator: Wyrażenie) Instrukcja typ elementów kolekcji Przykład: nazwa, za pomocą której można w Instrukcji odwoływać się do kolejnych elementów kolekcji, która jest wyliczana jako wartość Wyrażenia for(string s: kolekcja) System.out.println(s);
Pętla foreach for (type var : arr) { body-of-loop Równoważność for (int i = 0; i < arr.length; i++) { type var = arr[i]; body-of-loop for (type var : coll) { body-of-loop for (Iterator<type> iter = coll.iterator(); iter.hasnext(); ){ type var = iter.next(); body-of-loop
try{ <instrukcje> catch(typwyjątku refdowyjątku){ <obsługawyjątku> catch(typwyjątku refdowyjątku){ <obsługawyjątku>... catch(typwyjątku refdowyjątku){ <obsługawyjątku> finally{ <kodzawszewykonywany>
boolean metoda(...) { try { //instrukcje, które mogą spowodować //wyjątek catch (Exception e) { return false; finally { //uporządkowanie return true;
Throwable Exception Error RuntimeException
pochodne od klas RuntimeException i Error wyjątki niekontrolowane pozostałe wyjątki - kontrolowane, tzn.: metody zgłaszające te wyjątki wymieniają je jawnie w swojej deklaracji w klauzuli throws metody te mogą zgłaszać tylko wymienione w klauzuli throws wyjątki lub wyjątki ich podklas odwołania do tych metod wymagają jawnej obsługi ewentualnie zgłaszanych wyjątków:
Nieobsłużone wyjątki wydostając się poza main powodują przerwanie wykonywania programu oraz wypisanie komunikatu o błędzie: Exception in thread "main" java.lang.exception at test.wyjątki.głębiej(wyjątki.java:4) Szczegółowość informacji o umiejscowieniu błędu w kodzie zależy od ustawień kompilatora.
class Wyjątki { public static void main(string[] args) throws Exception { (new Wyjątki()).głęboko(); void głęboko() throws Exception { głębiej(); void głębiej() throws Exception { throw new Exception(); //kompilator wykryje miejsca, do których //sterowanie nigdy nie dotrze
class Wyjątki { public static void main(string[] args) throws Exception { głęboko(); static void głęboko() throws Exception { głębiej(); static void głębiej() throws MójWyjątek { throw new MójWyjątek(); Exception in thread "main" test.wyjątki at test.wyjątki.głębiej(wyjątki.java:114) at test.wyjątki.głęboko(wyjątki.java:111) at test.wyjątki.main(wyjątki.java:97)
static void głęboko() throws MójWyjątek { try { głębiej(); catch (MójWyjątek w) { w.fillinstacktrace(); throw w; //throw (MójWyjątek) w.fillinstacktrace(); //ta metoda jest zazwyczaj dziedziczona, aż z Throwable //czy przesłaniając można zmienić jej typ zwrotny Exception in thread "main" test.mójwyjątek at test.wyjątki.głęboko(wyjątki.java:120) at test.wyjątki.main(wyjątki.java:112)
Aby stworzyć własny wyjątek należy zdefiniować własną klasę dziedziczącą z podklasy Exception, np. class NowyWyjatek extends Exception {... w której można zawrzeć pola i metody służące dodatkowej informacji o przyczynach powstania wyjątku
Zgłaszanie wyjątku: jeśli nasza metoda ma zgłaszać wyjątek NowyWyjatek to musi podać w deklaracji, że może to zrobić tzn.: void naszametoda () throws nowywyjatek naszametoda sprawdza warunki powstania błędu, jeśli wystąpił błąd tworzy wyjątek: new NowyWyjatek(..) throw new NowyWyjatek
Podczas inicjalizacji statycznej klasy nowego obiektu nie mogą być zgłaszane żadne wyjątki kontrolowane. Każdy wyjątek kontrolowany, który może być zgłoszony w trakcie inicjalizacji atrybutów egzemplarza lub podczas wykonywania kodu z bloków inicjalizacji ({... ), musi być wymieniony w klauzulach throws wszystkich konstruktorów.
Studia informatyczne materiały dydaktyczne: http://wazniak.mimuw.edu.pl/
sirius.cs.put.poznan.pl/~inf89743/po/java.pdf