Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Vaše jistota na trhu IT Interní datové typy a výjimky Rudolf Pecinovský

Podobné prezentace


Prezentace na téma: "Vaše jistota na trhu IT Interní datové typy a výjimky Rudolf Pecinovský"— Transkript prezentace:

1 Vaše jistota na trhu IT Interní datové typy a výjimky Rudolf Pecinovský

2 Vaše jistota na trhu IT Obsah s odkazy ►VýjimkyVýjimky ►Výjimky kontrolované a nekontrolovanéVýjimky kontrolované a nekontrolované ►Definice vlastních výjimekDefinice vlastních výjimek ►Interní datové typyInterní datové typy ►Vnořené typy (nested, static inner)Vnořené typy (nested, static inner) ►Vnitřní třídy (inner classes)Vnitřní třídy (inner classes) ►Anonymní třídyAnonymní třídy ►Pojmenované lokální třídyPojmenované lokální třídy ►Rozhraní Comparable a ComparatorRozhraní Comparable a Comparator

3 Vaše jistota na trhu IT Výjimky ►Výjimečné situace v programech ►Ošetření nestandardních situací v Javě ►Zpráva o výjimce ►Klíčová slova ►Činnost ►Vyvolání

4 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 4 Výjimečné situace v programech ►V každém programu je alespoň jedna chyba – program na ni musí být připraven ►Starší programy ● Program vypsal chybové hlášení a ukončil činnost; ●V některých situacích (válcovací stolice, autopilot, …) nepřijatelné ● Funkce vrátí hodnotu signalizující chybu ●Programátor musí neustále testovat, co funkce vrací ● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou, do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné program zjistil kód poslední chyby ●Programátor musí neustále testovat, jaká je v proměnné hodnota ►Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí ošetření nestandardních situací

5 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 5 Ošetření nestandardních situací v Javě ►Výjimečná událost = problém, který brání dalšímu vykonávání části kódu ►Událost je výjimečná v tom, že na rozdíl od běžných problémů nemá program k vyřešení situace dost informaci ►Program může při výskytu výjimečné události vyvolat výjimku ►Výjimka (exception) objekt určený k přenosu informací o nastalém problému z místa jeho vzniku do místa, kde bude problém řešen

6 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 6 Postup při vyvolání výjimky 1.Vytvoří se výjimka = objekt typu Throwable (prakticky vždy instance některého z potomků) 2.Vytvořená výjimka se vyhodí = přeruší se běh programu v místě, kde výjimka vznikla, a začne se hledat místo, kde bude daná výjimka ošetřena 3.Ošetření výjimky (handler) by mělo uvést program do stavu, v němž může jeho vykonávání pokračovat ►Výjimka „probublává“ programem z místa vyhození stále výše a nenarazí-li cestou nikde na své ošetření, zachytí ji virtuální stroj, který na standardní chybový výstup vypíše zprávu o vzniku výjimky

7 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 7 Systémová zpráva o vzniku výjimky Název metody Informace o místě, odkud byla volána metoda, v níž došlo k vyhození výjimky Úplný název třídy včetně balíčku Číslo řádku zdrojáku, kde došlo k výjimce Název souboru se zdrojovým kódem Informace o místě, odkud byla volána metoda, která vyvolala metodu, v níž došlo k vyhození výjimky Zpráva o vzniku výjimky spolu s názvem vlákna, v němž k výjimce došlo (zde AWT-EventQueue-0) Popis druhu výjimky (aritmetická výjimka dělení nulou)

8 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 8 Klíčová slova související s výjimkami ► try (zkus) Označuje blok kódu, v němž může dojít k výjimce ► throw (hoď) Příkaz k vyhození výjimky; musí být následován odkazem na existující instanci ► catch (chyť) Blok ošetřující výjimku, která je zadána jako parametr ► finally (na konec) Blok s povinnými závěrečnými akcemi nezávisejícími na případném vzniku výjimky ► throws (hází) Uvození seznamu výjimek vyhazovaných danou metodou

9 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 9 Vyvolání a ošetření výjimky v kódu try { //Kód, který může vyvolat výjimky } catch( Typ1 id1 ) { //Ošetření výjimek typu Typ1 }... catch( TypN idN ) { //ošetření výjimek typu TypN } finally { //Kód, který se na závěr VŽDY provede }

10 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 10 try { příkaz1(); příkaz2(); příkaz3(); } catch ( xxxException e ) { příkazProOšetřeníChyby(); } catch (….. finally { ukončovacíPříkazy(); } Náznak činnosti nedojde k vyvolání výjimky = nedojde k chybě Při provádění metody příkaz2 dojde k chybě Byla vyhozena výjimka tohoto typu nebo typu některého z potomků

11 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 11 try { příkaz1(); příkaz2(); příkaz3(); } catch ( xxxException e ) { příkazProOšetřeníChyby(); } catch (….. finally { ukončovacíPříkazy(); } dalšíPříkaz(); Náznak činnosti nedojde k vyvolání výjimky = nedojde k chybě Při provádění metody příkaz2 dojde k ošetřené chybě Byla vyhozena výjimka tohoto typu nebo typu některého z potomků Při provádění metody příkaz2 dojde k NEošetřené chybě Ošetření nebylo nalezeno => provede se blok finally a opouští se metoda Ostatní bloky catch se přeskočí

12 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 12 try { příkaz1(); příkaz2(); příkaz3(); } catch ( xxxException e ) { příkazProOšetřeníChyby(); } catch (….. finally { ukončovacíPříkazy(); } dalšíPříkaz(); Náznak činnosti – řádný průběh nedojde k vyvolání výjimky = nedojde k chybě Bloky catch se přeskočí

13 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 13 try { příkaz1(); příkaz2(); příkaz3(); } catch ( xxxException e ) { příkazProOšetřeníChyby(); } catch (….. finally { ukončovacíPříkazy(); } dalšíPříkaz(); Náznak činnosti – ošetřený výjimka Při provádění metody příkaz2 dojde k ošetřené chybě Byla vyhozena výjimka tohoto typu nebo typu některého z potomků Ostatní bloky catch se přeskočí

14 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 14 try { příkaz1(); příkaz2(); příkaz3(); } catch ( xxxException e ) { příkazProOšetřeníChyby(); } catch (….. finally { ukončovacíPříkazy(); } dalšíPříkaz(); Náznak činnosti – neošetřená výjimka Při provádění metody příkaz2 dojde k NEošetřené chybě Ošetření nebylo nalezeno => provede se blok finally a opouští se metoda

15 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 15 Vyvolání výjimky ►Instanci nemusíme vytvářet až v příkazu throw, můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat public class Xyz implements Comparable { public bolean compareTo( Object o ) { if( !(o instanceOf Xyz) ) throw new ClassCastException ( "\nPokus o porovnání s neporovnatelnou" + " instancí " + o ); //Zjištění, kdo je větší return vysledek; }

16 Vaše jistota na trhu IT Výjimky kontrolované a nekontrolované ►Hierarchie výjimek ►Pořadí výjimek v blocích catch ►Metody generující výjimky ►Metody třídy Throwable ►Zřetězené výjimky ►Převod kontrolovaných na nekontrolované

17 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 17 Charakteristika ►Výjimky, které jsou potomky třídy RuntimeException nebo Error označujeme jako nekontrolované (unchecked), protože překladač nekontroluje, zda je na ně program připraven ►Ostatní výjimky označujeme jako kontrolované (checked), protože překladač kontroluje dodržení pravidel: ● Každá metoda, která může vyhodit kontrolovanou výjimku, se musí k této skutečnosti veřejně přihlásit ● Každé použití metody, která může vyhodit kontrolovanou výjimku, musí být buď uzavřeno v bloku try…catch, nebo se volající metoda musí přihlásit k tomu, že může také vyhodit danou kontrolovanou výjimku ►Nekontrolované výjimky ohlašují chyby v programu, kontrolované výjimky očekávatelné situace, na jejichž výskyt má být program připraven a měl by na ně umět reagovat

18 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 18 Hierarchie výjimek NEKONTROLOVANÉ UNCHECKED NEKONTROLOVANÉ UNCHECKED

19 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 19 Pořadí výjimek v blocích catch ►Třída NumberFormatException je potomkem třídy RuntimeException try { } catch (RuntimeException e) { } catch (NumberFormatException e){ } try { } catch (NumberFormatException e) { } catch (RuntimeException e){ } Syntaktická chyba, na druhý blok catch nikdy nedojde Obrácené pořadí bloků catch vše vyřeší

20 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 20 Metody generující výjimky ►Java vyžaduje, aby programy, které používají metody schopné vyvolat kontrolované výjimky, byly o této schopnosti používaných metod informovány => pak vědí, které výjimku musí umět zachytit a ošetřit ►Všechny kontrolované výjimky, které může metoda vyhodit, musí deklarovat v hlavičce za klíčovým slovem throws ►Deklarace vyhazování nekontrolovaných výjimek není povinná public void metoda() throws KontrolovanáVýjimka1, KontrolovanáVýjimka2 { // Tělo metody }

21 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 21 Metody třídy Throwable ► String getMessage() Vrátí zprávu popisující danou výjimku ► String toString() Vrátí název třídy výjimky následovaný případnou zprávou ► void printStackTrace() Vytiskne toString() následovaný sadou informací o volající posloupnosti, která vedla k vzniku výjimky ► Throwable fillInStackTrace() Připraví nové informace o volací posloupnosti vedoucí k místu zavolání této metody ► StackTraceElement[] getStackTrace() Vrátí uchované informace o volací posloupnosti dané výjimky

22 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 22 Zřetězené výjimky ►V některých situacích je vhodné v rámci ošetření výjimky vyvolat jinou výjimku, a přitom umožnit zjistit, která výjimka byla prvotním hybatelem celé akce ►Řada výjimek má mezi svými konstruktory i takové, které akceptují jako poslední parametr odkaz na výjimku, jež byla příčinou vyvolání dané výjimky ►Chce-li se program zeptat výjimky na výjimku, která ji způsobila, použije metodu public Throwable getCause() ►Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka nahrazena jinou, označována textem caused by:

23 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 23 Ukázka výpisu při zřetězení výjimek HighLevelException: MidLevelException: LowLevelException at Junk.a(Junk.java:13) at Junk.main(Junk.java:4) Caused by: MidLevelException: LowLevelException at Junk.c(Junk.java:23) at Junk.b(Junk.java:17) at Junk.a(Junk.java:11)... 1 more Caused by: LowLevelException at Junk.e(Junk.java:30) at Junk.d(Junk.java:27) at Junk.c(Junk.java:21)... 3 more

24 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 24 Převod kontrolovaných na nekontrolované ►Ošetřování kontrolovaných výjimek obtěžuje ►Víme-li, že k dané výjimce nejspíš nedojde a ošetřujeme-li ji pouze proto, že na tom překladač trvá, můžeme pro případ, že by k výjimce přece jenom došlo zaměnit kontrolovanou výjimku za nekontrolovanou public void prevod( String s ) { try { prověř( s ); } catch( Exception ex ) { throw new RuntimeException( " Neprověřeno! ", ex ); }

25 Vaše jistota na trhu IT Definice vlastních výjimek ►Hierarchie výjimek ►Pořadí výjimek v blocích catch ►Metody generující výjimky ►Metody třídy Throwable ►Vlastní výjimky ►Zásady správného používání výjimek

26 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 26 Definice vlastních výjimek ►Výjimky jsou zcela běžné třídy; považujeme-li to proto za vhodné, můžeme definovat i vlastní ►Před definicí nové výjimky bychom si měli ujasnit, bude-li kontrolovaná či nekontrolovaná; podle toho definujeme jejího předka ►Název výjimek končí dle konvencí slovem Exception před nímž je naznačena podstata dané výjimky ● IllegalArgumetnException ● NoSuchMethodException ● BadStringOperationException

27 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 27 Příklad vlastní kontrolované výjimky public class VelkýPrůšvihException extends Exception { public VelkýPrůšvihException() {}; public VelkýPrůšvihException( String zpráva ) { super( zpráva ); } public VelkýPrůšvihException(String zpráva, Throwable původce ) { super( zpráva, původce ); }

28 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 28 Test správného vyhození výjimky ►Na vytvářených programech je třeba otestovat i to, že v definovaných situacích vyhodí požadovanou výjimku public void testVyhozeníVýjimky() { try { metodaKteráMáVyhoditVýjimku(); } catch ( VelkýPrůšvihException vpe ) { return; } fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" ); }

29 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 29 Zásady správného používání výjimek1/2 Neignorujte výjimky ►Výjimky, o nichž víte, že nemohou nastat, převeďte na nekontrolované pro případ, že by v budoucích verzích programu nastat mohly ►Při ošetřování výjimek, které nastat mohou, ale nemají vliv na chod programu, vložte do těla ošetření alespoň vysvětlující komentář try { //Nějaký kód } catch(Exception e){}

30 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 30 Zásady správného používání výjimek2/2 ►Používejte výjimky pouze k ošetření výjimečných stavů ►Kontrolované výjimky používejte u stavů, z nichž se lze zotavit, jinak použijte výjimky nekontrolované ►Vyhýbejte se zbytečnému používání kontrolovaných výjimek ● Programátory ošetřování kontrolovaných výjimek obtěžuje a mají pak tendenci je ošetřovat prázdným blokem catch ►Dávejte přednost standardním výjimkám, vyvolávejte výjimky odpovídající dané abstrakci ● Programátoři by měli z názvu výjimky poznat, co se stalo ● Standardní výjimky mají všeobecně známý význam ►Snažte se o atomičnost selhání; i po vyhození výjimky by měl být objekt v dobře definovaném stavu

31 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 31 Zásady správného používání výjimek3/2 ►Doplňujte výjimky zprávami, výjimka by sama měla poskytnout dostatek informací a neměla by programátora nutit k podrobnější analýze programu ►Dokumentujte vyvolávané výjimky v dokumentačních komentářích pomocí ►Nedělejte bloky try zbytečně velké, kód uvnitř těchto bloků se neoptimalizuje ►Umíte-li výjimku v metodě ošetřit, udělejte to ►Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné (stejné či jiné instance), použijte výjimku.

32 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 32 Nejčastěji používané výjimky1/2 ► IllegalArgumentException Byla zadána nepovolená hodnota parametru ● Např. chci nastavit zápornou velikost grafického tvaru ► IllegalStateException V daném stavu objektu nelze metodu provést ● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu ► NullPointerException Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz, nebo byl předán nepovolený prázdný odkaz v parametru ► ArrayIndexOutOfBoundException Byly zadány špatné meze pole, buď záporné nebo moc velké

33 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 33 Nejčastěji používané výjimky2/2 ► ConcurrentModificationException V průběhu iterace byla změněna struktura kontejneru ● Např. byl do kontejneru přidán prvek ► NumberFormatException Je požadován špatný převod řetězce na číslo či naopak ● Chci-li např. převést na číslo řetězec, který není číslem ● Častá chyba v metodách String.format či PrintStream.printf ► ClassCastException Požadované přetypování není možné ► UnsupportedOperationException Požadovaná operace není podporována (např. chci přidat prvek do neměnného kontejneru)

34 Vaše jistota na trhu IT Interní datové typy ►Charakteristika ►Rozdělení ►Globální zanořené třídy ►Vnořené třídy ►Vnitřní třídy – omezení, důvody zavedení ►Anonymní třídy – definice, omezení, použití ►Pojmenované lokální třídy

35 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 35 Charakteristika ►Typy definované uvnitř jiných typů ►Typy mají členy: ● Datové – atributy ● Funkční – metody ● Typové – interní typy ►Každý typ, tj. i interní, má vlastní soubor *.class ►Mohou být potomky libovolné viditelné třídy a implementovat libovolné viditelné rozhraní ►Jsou uvnitř svých vnějších typů, a proto vidí i na jejich soukromé (private) členy

36 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 36 Rozdělení interních tříd ►Globální – mimo bloky kódu, tj. na úrovni atributů a metod ● Statické – Vnořené (nested, embedded, static inner) ● Nestatické – Vnitřní (inner) ►Lokální – uvnitř metod a bloků kódu ● Pojmenované (named) ● Anonymní (anonymous)

37 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 37 Globální interní typy ►Pro jejich dostupnost a její nastavení platí totéž, co pro dostupnost ostatních členů, tj. atributů a metod ►Mohou mít nastaveny kterýkoliv modifikátor přístupu ● public ● protected ● „package private“ ● private ►Zvenku se k nim přistupuje stejně jako k ostatním členům, tj. kvalifikují se svoji třídou či instancí (např. java.awt.geom.Point2D.Double )

38 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 38 Lokální třídy ►Deklarovány uvnitř bloků kódu ● Nejen uvnitř metod, ale uvnitř libovolného bloku kódu ►Jsou soukromou záležitostí svého bloku ● Obdobně jako lokální proměnné jsou zvenku nedosažitelné ►Mohou to být pouze třídy, nelze definovat lokální interface ►Instance lokální třídy je možno vyvážet mimo daný blok; tam se vydávají za instance svého předka či implementovaného rozhraní ● Hlavní důvod definice lokálních tříd

39 Vaše jistota na trhu IT Vnořené typy (nested, static inner)

40 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 40 Charakteristika ►Deklarovány s modifikátorem static (rozhraní static nepotřebují, protože jiná být nemohou) ►Jsou to zcela obyčejné typy se všemi jejich možnostmi a omezeními, s výjimkou viditelnosti / dosažitelnosti ►Vnoření typu do jiného ovlivní pouze ● Viditelnosti daného typu z okolí ● Dosažitelnost objektů z definic ve vnořené třídě (z rozhraní není kam dosahovat) ►Vnoření je pouze otázka jmenného prostoru => vnořené typy můžeme definovat i uvnitř rozhraní (např. java.util.Map.Entry )

41 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 41 Důvody zavedení: ►Třída potřebuje definovat vlastní datový typ, nejčastěji přepravku (pak bývají soukromé) ►Potřebujeme definovat datový typ, jehož instance budou mít přístup k soukromým atributům své vnější třídy ►Pro rozhraní je občas vhodné definovat typickou implementaci deklarovaných metod (adaptér) ►Vnější třída je rodičem svých vnitřních, které přímo přistupují k jejím soukromým atributům

42 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 42 Příklad 1: třída Směr8 public enum Směr8 { //== HODNOTY VÝČTOVÉHO TYPU ================================================== VÝCHOD ( 1, 0, "S", "VÝCHOD", "VYCHOD"), SEVEROVÝCHOD( 1, -1, "SV", "SEVEROVÝCHOD", "SEVEROVYCHOD"), SEVER ( 0, -1, "S", "SEVER", "SEVER"), SEVEROZÁPAD ( -1, -1, "SZ", "SEVEROZÁPAD", "SEVEROZAPAD"), ZÁPAD ( -1, 0, "Z", "ZÁPAD", "ZAPAD"), JIHOZÁPAD ( -1, 1, "JZ", "JIHOZÁPAD", "JIHOZAPAD"), JIH ( 0, 1, "J", "JIH", "JIH"), JIHOVÝCHOD ( 1, 1, "JV", "JIHOVÝCHOD", "JIHOVYCHOD"), ; //== KONSTANTNÍ ATRIBUTY TŘÍDY =============================================== public static final int SMĚRŮ = 8; private static final int MASKA = 7; private static final Map názvy = new HashMap ( SMĚRŮ*3 ); private static final int[][] posun = new int[SMĚRŮ][2]; private static final Směr8[] SMĚRY = values(); static { for( Směr8 s : SMĚRY ) { posun[s.ordinal()][0] = s.přepravka.dx; posun[s.ordinal()][1] = s.přepravka.dy; názvy.put( s.přepravka.zkratka, s ); názvy.put( s.přepravka.název, s ); názvy.put( s.přepravka.názevBHC,s ); s.přepravka = null; } //== DOČASNÉ ATRIBUTY INSTANCÍ =============================================== private static class Přepravka { int dx, dy; String zkratka, název, názevBHC; } Přepravka přepravka; //== KONSTRUKTORY A TOVÁRNÍ METODY =========================================== private Směr8( int dx, int dy, String zkratka, String název, String názevBHC ) { přepravka = new Přepravka(); přepravka.dx = dx; přepravka.dy = dy; přepravka.zkratka = zkratka; přepravka.název = název; přepravka.názevBHC = názevBHC; } Deklarace hodnot (veřejných konstant) daného typu Mapa pro odvození instance ze zadaného názvu Instance si svá data nepamatují ve vlastních atributech, ale v polích, které jsou atributy třídy Statický inicializační blok inicializující pole a mapu Přepravka pro dočasné uchování hodnot zadaných konstruktoru, než je bude možno uložit do mapy a příslušných polí Konstruktor ukládá všechny parametry do přepravky, aby je bylo možno vyzvednout ve statickém inicializačním bloku

43 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 43 Příklad 2: IPosuvný.Adaptér public interface IPosuvný extends IKreslený { public Pozice getPozice(); public void setPozice( Pozice pozice ); public void setPozice( int x, int y ); public static class Adaptér implements IPosuvný { public Pozice getPozice() { throw new UnsupportedOperationException(); } public void setPozice( Pozice pozice ) { throw new UnsupportedOperationException(); } public void setPozice( int x, int y ) { throw new UnsupportedOperationException(); } public void nakresli( Kreslítko kreslítko ) { throw new UnsupportedOperationException(); } public class Třída extends IPosuvný.Adaptér { // Definice těla třídy }

44 Vaše jistota na trhu IT Vnitřní třídy (inner classes)

45 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 45 Charakteristika ►Deklarovány bez modifikátoru static ►Instance vnitřní třídy jsou navázány na instanci vnější třídy –> mají deklarován skrytý konstantní atribut obsahující odkaz na příslušnou instancí vnější třídy ►Tato vazba potřebuje implementaci => jako vnitřní typ není možno definovat rozhraní ►Atribut je skrytý, tj. neuvádí se, ale můžeme jej používat –> získání odkazu na instanci vnější třídy: Vnější.this

46 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 46 Konstrukce instance vnitřní třídy ►V metodě instance ● Odkaz na příslušnou instanci vnější třídy předá konstruktoru překladač (vezme this a předá je) ►V metodě třídy ● Odkaz na příslušnou instanci vnější třídu musí konstruktoru vnitřní třídy předat programátor – učiní tak kvalifikací operátoru new instancí vnější třídy, na níž bude vytvářená instance vnitřní třídy napojena – např.: Vně vně = new Vně(); Vně.Vni vni = vně.new Vně.Vni();

47 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 47 Omezení ►Nesmějí mít statické atributy a metody – nevědělo by se, jak moc jsou statické ● Pouze v rámci napojené instance ● V rámci celé vnější třídy ►Místo zavádění statických atributů a metod je třeba definovat potřebné atributy a metody v příslušné vnější třídě ►Při dědění od vnitřní třídy je třeba dceřinému konstruktoru předat v parametru odkaz na její instanci – složité, nepoužívat

48 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 48 Důvody zavedení ►Je třeba exportovat objekt zadaného typu, který by měl přístup k soukromým složkám instance (např. iterátor) ►Je potřeba pomocný (=soukromý) typ, jehož instance budou mít přímou vazbu na instance své vnější třídy ►Alternativa pro některé anonymní třídy (někdo nemá anonymní třídy rád, protože znepřehledňují kód)

49 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 49 Příklad: Iterátor public class ItPole implements Iterable { private final Položka [] pole; //Pole položek typu Položka public ItPole(Položka[] pole) { this.pole = pole.clone() } public Iterator iterator() { return new Iter(); } private class Iter implements Iterator { int index = 0; public boolean hasNext() { return (index < pole.length ); } public Položka next() { return pole[ index++ ]; } public void remove() { throw new UnsupportedOperationException(); } private static void test() { ItPole ip = new ItPole ( new Integer[] { 1, 3, 5, 7, 11, 13, 17, 19 } ); for( Integer i : ip ) { System.out.println( i + "^2 = " + i*i ); }

50 Vaše jistota na trhu IT Anonymní třídy

51 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 51 Charakteristika ►Jejich definice je součástí příkazu k vytvoření instance; je to na poslední chvíli uvedená definice třídy vytvářené instance ►Definice anonymní třídy jsou součástí příkazu vytvoření instance, a proto vystupují ve zdrojovém textu jako výraz (píše se za nimi středník či čárka) ►Nemohou mít vlastní konstruktor; je-li potřeba, používá se místo něj nestatický inicializační blok ►Mohou používat pouze konečné lokální proměnné (konstanty) některého z bloků, v nichž je anonymní třída definována ● Důvod: doba života bloku × instance

52 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 52 Zápis ►Tváříme se, že voláme konstruktor rodiče, ale protože ve skutečnosti chceme zkonstruovat potomka, jehož třída navíc ještě neexistuje, tak si ji narychlo vytvoříme ►Podle zadaných parametrů se pozná, který z rodičovských konstruktorů vytvoří příslušný podobjekt ►Definice tříd implementujících rozhraní se „tváří“, že rozhraní má implicitní konstruktor; ve skutečnosti se volá konstruktor třídy Object new Rodič(parametry) { //Definice potřebných metod }

53 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 53 Omezení1/2 ►Mohou používat pouze konečné proměnné (konstanty) bloků, v nichž jsou definovány ● Důvod: doba života bloku × instance ● Je-li použitou proměnnou parametr, i on musí být definován jako konečný ►Nemohou mít vlastní konstruktor; je-li potřeba, používá se místo něj inicializační blok IPojmenovaný vytvoř( final String název ) { return new IPojmenovaný() { String jméno; { jméno = název; } public String getNázev() { return jméno; } }; } IPojmenovaný vytvoř( final String název ) { return new IPojmenovaný() { public String getNázev() { return název; } }; } Lepší řešení

54 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 54 Omezení2/2 ►Nemohou definovat statické metody ● Teoreticky je místo nich třeba definovat potřebné metody ve vnější třídě, ale tak složité anonymní třídy se nepoužívají ►Nemohou definovat statické atributy ● Místo proměnných statických atributů je třeba definovat atributy ve vnější třídě ● Místo konstantních atributů lze použít konstanty některého z bloků v nichž je definice anonymní třídy zanořena

55 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 55 Použití 1: Posluchači událostí1/3 ►Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instance požadovaného typu ● Posluchači událostí ● Vlákna ● … JButton tlačítko = new JButton( OK ); tlačítko.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent ae ) { potvrzeno(); } ); Instance anonymní tříd je použita jako parametr

56 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 56 Použití 2: Vytvoření ihned použitého objektu ►Objekt vlákna (instance třídy Thread) monu nejprve vytvořit a v dalším příkazu použít ►Stejně dobře ale mohu čerstvě vytvořený objekt ihned, tj. v témže příkazu použít Thread t = new Thread( "Ukázka" ) { public void run() { metoda(); } }; t.start(); new Thread( "Ukázka" ) { public void run() { metoda(); } }.start();

57 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 57 Použití 3: Funkční výčtové typy2/3 ►Instance funkčního výčtového typy jsou instancemi potomka tohoto typu ►Z venku není dovnitř potomků vidět, takže nevím, jaké metody deklarují => ►Metody instancí funkčních výčtových typů musí být v rodiči deklarovány jako abstraktní – tím se zviditelní public enum Operace { PLUS { public int proveď( int a, int b) { return a + b; } }, MINUS { public int proveď( int a, int b) { return a - b; } }; public abstract proveď( int a, int b ); } //... Operace op = PLUS; int výsledek = op.proveď( x, y ); //...

58 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 58 Použití 4: Vektory metod3/3 public interface IOperace { public int proveď( int a, int b ); } IOperace[] op = { new IOperace() { public int proveď( int a, int b ) { return a * b; } }, new IOperace() { public int proveď( int a, int b ) { return a / b; } } }; Random rnd = new Random(); //... int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y); //...

59 Vaše jistota na trhu IT Pojmenované lokální třídy

60 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 60 Charakteristika ►Jsou velmi podobné anonymním třídám ►Odchylky: ● Mohou mít vlastní konstruktor ● Mají jména, takže jejich instance mohu vytvářet na více místech programu ►Společná omezení ● Nemohou mít statické členy ● Z lokálních proměnných bloků, v nichž jsou definovány, mohou používat pouze konstanty

61 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 61 Příklad: Filtr souborů private static void najdiVeSlozce( File koren, Class predek, String balicek, Collection >tridy ) { // Filtr souboru k dalsi analyze - pousti jen class-soubory class Prelozene implements java.io.FileFilter { public boolean accept( File soubor ) { boolean slozka, trida, zajimavy; zajimavy = (slozka = soubor.isDirectory()) || (trida = soubor.getName().endsWith( ".class" ) ); return zajimavy; } for( File f : koren.listFiles( new Prelozene() ) ) { zpracujSoubor( f ); }

62 Vaše jistota na trhu IT Rozhraní Comparable a Comparator ►Typy s definovaným pořadím ►Rozhraní Comparable ►Nativní třídění polí a seznamů ►Problémy související s tříděním ►Požadavky rozhraní Comparator ►Třídění s pomocí komparátoru ►Další metody využívající porovnání ►Návrhový vzor Příkaz 89–93

63 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 63 Typy s definovaným pořadím ►Řada hodnotových objektových typů má definované porovnávání hodnot ►Porovnatelnost hodnot instancí deklaruje třída implementací rozhraní java.lang.Comparable ►Rozhraní vyžaduje implementaci jediné metody int compareTo( T t ) ►Vracená hodnota: ● < 0 je-li this < t ● = 0 je-li this == t ● > 0 je-li this > t

64 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 64 Požadavky na metodu compareTo( T) ►Antisymetričnost: sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) ● Vztahuje se i na výjimky, tj. když jedno porovnání vyhodí výjimku, mělo by ji vyhodit i to sdružené ►Transitivnost: (x.compareTo(y)>0 && y.compareTo(z)>0) => x.compareTo(z)>0 ►Odvoditelnost: x.compareTo(y)==0 => sgn(x.compareTo(z)) == sgn(y.compareTo(z)) ►Vřelé doporučení: konsistence s equals(Object) : (x.compareTo(y)==0) == (x.equals(y))

65 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 65 Nativní třídění polí a seznamů ►K třídění polí slouží metody java.util.Arrays.sort(T[] ta) java.util.Arrays.sort(T[] ta, int from, int to) kde typ T může být libovolný primitivní či objektový typ ►K třídění seznamů slouží metoda java.util.Coolections.sort(List lt) kde typ T může být libovolný objektový typ implementující Comparable ►U objektových typů se předpokládá, že ● Všechny porovnávané instance implementují rozhraní Comparable ● Instance jsou vzájemně porovnatelné V opačném případě metoda vyvolá ClassCastException

66 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 66 Problémy související s tříděním ►V různých fázích práce programu potřebuji třídit podle různých kritérií ● Např. jednou s rozlišováním velikosti písmen a podruhé bez něj ►Potřebuji porovnávat instance tříd, které nativně vzájemné porovnání nepodporují ● Např. hrušky s jablky podle jejich váhy ►Potřebuji třídit podle jiného kritéria, než je nativní kritérium implementované metodou compareTo(Object) ● Zákazníci jsou nativně tříděni dle abecedy, ale já je potřebuji setřídit podle jejich dosažitelnosti, solventnosti apod. ►Třída žádné porovnávací kritérium nedefinuje, ale pro danou situaci mám nějaké vymyšlené ● Třídím experimenty podle odhadované doby trvání

67 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 67 Rozhraní java.util.Comparator ►Předchozí problémy lze řešit definicí třídy implementující rozhraní java.util.Comparator ►Rozhraní Comparator vyžaduje definici metody int compare(T t1, T t2) ►Vracená hodnota i požadavky na metodu jsou stejné jako u metody compareTo(Object) zaměníme-li u ní this za t1 ►Třída implementující rozhraní Comparator bývá často definována jako interní (většinou vnořená)

68 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 68 Třídění polí a seznamů pomocí komparátoru ►K třídění polí slouží metody Arrays.sort(T[] ta, Comparator c) Arrays.sort(T[] ta, int from, int to, Comparator c) ►K třídění seznamů slouží metoda Coolections.sort(List lt, Comparator c) ►Instance komparátoru předaná jako parametr musí umět vzájemně porovnat všechny prvky v tříděném poli či seznamu; v opačném případě metoda vyvolá ClassCastException

69 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 69 Příklad: Třídění nativní a modulo public class Modulo2 implements Comparable { private final int hodnota; private final int modul; public Modulo2( int h ) { hodnota = h; modul = h % 10; }//============================================================= public String toString() { return String.format( "%2s", hodnota); }//============================================================= private static void tiskni( String s, Modulo2[] mm) { System.out.println( s + Arrays.asList( mm ) ); }//============================================================= public static final void test() { Random rnd = new Random(); Modulo2[] mm = new Modulo2[20]; for( int i=0; i < mm.length; mm[i++] = new Modulo2(rnd.nextInt(100)) ); tiskni( "Výchozí: ", mm ); Arrays.sort( mm ); tiskni( "Setříděné: ", mm ); Arrays.sort( mm, new Comp() ); tiskni( "Comparator:", mm ); }//============================================================= public int compareTo(Modulo2 m) { return (hodnota - m.hodnota); }//============================================================= private static class Comp implements Comparator { public int compare( Modulo2 a, Modulo2 b) { if( a.modul != b.modul ) return (a.modul - b.modul); else return a.hodnota - b.hodnota; }

70 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 70 Příklad: Třídění nativní a modulo public class Modulo2 implements Comparable { private final int hodnota; private final int modul; public Modulo2( int h ) { hodnota = h; modul = h % 10; }//============================================================= public String toString() { return String.format( "%2s", hodnota); }//============================================================= private static void tiskni( String s, Modulo2[] mm) { System.out.println( s + Arrays.asList( mm ) ); }//============================================================= public static final void test() { Random rnd = new Random(); Modulo2[] mm = new Modulo2[20]; for( int i=0; i < mm.length; mm[i++] = new Modulo2(rnd.nextInt(100)) ); tiskni( "Výchozí: ", mm ); Arrays.sort( mm ); tiskni( "Setříděné: ", mm ); Arrays.sort( mm, new Comp() ); tiskni( "Comparator:", mm ); }//============================================================= public int compareTo(Modulo2 m) { return (hodnota - m.hodnota); }//============================================================= private static class Comp implements Comparator { public int compare( Modulo2 a, Modulo2 b) { if( a.modul != b.modul ) return (a.modul - b.modul); else return a.hodnota - b.hodnota; } Výchozí: [99, 79, 18, 81, 47, 88, 88, 42, 56, 85, 61, 23, 41, 44, 3, 46, 74, 52, 17, 23] Setříděné: [ 3, 17, 18, 23, 23, 41, 42, 44, 46, 47, 52, 56, 61, 74, 79, 81, 85, 88, 88, 99] Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74, 85, 46, 56, 17, 47, 18, 88, 88, 79, 99]

71 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 71 Další metody využívající porovnání1/2 ►K vyhledání prvku v setříděném polí slouží metody Arrays.binarySearch(T[] ta, T klíč) Arrays.binarySearch(T[] ta, T klíč, Comparator c) kde typ T může být libovolný primitivní či objektový typ ►K vyhledání prvku v setříděném seznamu slouží metody Collections.binarySearch(List lt, T klíč) Collections.binarySearch(List ta, T klíč, Comparator c) ►K získání komparátoru, který třídí v obráceném pořadí, slouží Collections.reverseOrder() Collections.reverseOrder(Comparator cmp)

72 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 72 Další metody využívající porovnání2/2 ►K vyhledání největšího prvku v kolekci slouží metody Collections.max(Collection coll) Collections.max(Collection coll, Comparator c) ►K vyhledání nejmenšího prvku v kolekci slouží metody Collections.max(Collection coll) Collections.max(Collection coll, Comparator c)

73 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 73 Zdrojový kód metody max(Collection ) //Deklarace typových parametrů jsou zjednodušené public static > T max(Collection coll) { Iterator i = coll.iterator(); T candidate = i.next(); while(i.hasNext()) { T next = i.next(); if (next.compareTo(candidate) > 0) candidate = next; } return candidate; } Kolekcí budeme procházet pomocí iterátoru Připravíme si kandidáta na maximum Procházíme zbytkem kolekce, a je-li někdo větší než kandidát, prohlásíme jej za lepšího kandidáta

74 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 74 Zdrojový kód verze s komparátorem //Deklarace typových parametrů jsou zjednodušené public static T max(Collection coll, Comparator comp) { if (comp==null) return (T)max((Collection ) (Collection) coll); Iterator i = coll.iterator(); T candidate = i.next(); while(i.hasNext()) { T next = i.next(); if (comp.compare(next, candidate) > 0) candidate = next; } return candidate; } private interface SelfComparable extends Comparable {} Je-li zadán prázdný odkaz na komparátor, zkusíme verzi bez komparátoru Verze bez komparátoru vyžaduje nativně porovnatelné objekty – definuje si soukromé vnořené rozhraní, na něž se pokusí instance přetypovat Je-li dodán komparátor, připraví si iterátor a kandidáta na maximum Pak pokračuje stejně jako minule, jenom s jinou metodou porovnání hodnot

75 Vaše jistota na trhu IT Děkuji za pozornost ►Rudolf Pecinovský mail: ICQ:

76 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 76

77 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 77 Příklad: Fronta – atributy a metody public class Fronta implements Iterable { private final List prvky = new LinkedList (); public void zařaď( E e ) { prvky.add( e ); } public E další() { if( prvky.size() == 0 ) return null; E ret = prvky.get(0); prvky.remove(0); return ret; } public Iterator iterator() { return new MůjIterator( this ); }

78 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 78 Příklad: Fronta – vnořená třída private class MůjIterator implements Iterator { int pořadí = 0; Fronta f; MůjIterator( Fronta fronta ) { f = fronta; } public boolean hasNext() { return (pořadí < f.prvky.size()); } public E next() { return f.prvky.get( pořadí++ ); } public void remove() { CHYBA(); } Neplnohodnotná implementace – volání metody způsobí chybu Protože je definována uvnitř třídy, má přístup k soukromým složkám jejích instancí

79 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 79 Příklad: Fronta – Test public static void test() { Random rnd = new Random(); Fronta fronta = new Fronta (); System.out.println("===== Začátek testu ====="); System.out.println("Přidáváme:"); for( int i=0; i < 5; i++ ) { Integer číslo = new Integer(rnd.nextInt(100)); fronta.zařaď( číslo ); System.out.print("Přidáno: " + číslo); System.out.print (" Stav:"); //Použití cyklu for(:) na instance třídy Fronta for( Integer fi : fronta ) System.out.print( " " + fi ); System.out.println(""); } System.out.println("\nOdstraňujeme:"); for(;;) { Integer další = fronta.další(); if( další == null ) break; // > System.out.print("Obslouženo: " + další); System.out.print (" Stav:"); //Použití cyklu for(:) na instance třídy Fronta for( Integer fi : fronta ) System.out.print( " " + fi ); System.out.println(""); } System.out.println("===== Fronta obsloužena ====="); }

80 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 80 Pgm Používaná písma a objekty ► Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Demi) ● Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Medium) ● Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Cond) ►Příliš žluťoučký kůň úpěl ďábelské ódy (Heavy) ● Příliš žluťoučký kůň úpěl ďábelské ódy (Franklin Gothic Book) ● Příliš žluťoučký kůň úpěl ďábelské ódy (Comic Sans MS) ● Příliš žluťoučký kůň úpěl ďábelské ódy (Consolas) Program Keyword Opakování Příliš žluťoučký kůň úpěl ďábelské ódy

81 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 81 Konvence syntaktických definic Syntaktická definice = pravidla zápisu konstrukce jazyka Název–Název definované součásti součást –Název součásti definované jinde program –Text, který se přímo použije (opíše) [ ]–Obsah hranatých závorek je volitelný { | }–Výběr z několika možností oddělených | –Druhou možností je psaní možností pod sebe …–Předchozí položka se může opakovat ¶–Definice pokračuje na dalším řádku kde bude navíc odsazená Příklad:Identifikátor:písmeno [ { písmeno | číslice } ] … Číslice: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 Originál: P02_Prvni_kod.ppt#23. Konvence syntaktických definicP02_Prvni_kod.ppt#23. Konvence syntaktických definic


Stáhnout ppt "Vaše jistota na trhu IT Interní datové typy a výjimky Rudolf Pecinovský"

Podobné prezentace


Reklamy Google