Vaše jistota na trhu IT Interní datové typy a výjimky Rudolf Pecinovský [email protected] Vaše jistota na trhu IT Obsah s odkazy ►Výjimky ►Výjimky kontrolované a nekontrolované ►Definice vlastních výjimek ►Interní.

Download Report

Transcript Vaše jistota na trhu IT Interní datové typy a výjimky Rudolf Pecinovský [email protected] Vaše jistota na trhu IT Obsah s odkazy ►Výjimky ►Výjimky kontrolované a nekontrolované ►Definice vlastních výjimek ►Interní.

Slide 1

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 2

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 3

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 4

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 5

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 6

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 7

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 8

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 9

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 10

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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:");
VŠE – 05
79
Copyrightfor(;;)
© 2006, Rudolf Pecinovský
{


Slide 11

Vaše jistota na trhu IT

Interní datové
typy a výjimky
Rudolf Pecinovský
[email protected]

Vaše jistota na trhu IT

Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
►Interní datové typy
►Vnořené typy (nested, static inner)
►Vnitřní třídy (inner classes)
►Anonymní třídy
►Pojmenované lokální třídy
►Rozhraní Comparable a Comparator

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í

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

4

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

5

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

6

Systémová zpráva o vzniku 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)

Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
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
Copyright © 2006, Rudolf Pecinovský

Název metody
VŠE – 05

Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

8

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

9

Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

12

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

13

Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě

try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

14

Vyvolání výjimky
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;
}
}

► 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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

15

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é

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
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

17

Hierarchie výjimek

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

18

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

VŠE – 05

19

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
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

20

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

21

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:

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

22

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

23

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

24

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

26

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 );
}
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

27

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" );
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

28

Zásady správného používání výjimek

1/2

Neignorujte
výjimky

try {
//Nějaký kód
}
catch(Exception e){}

► 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ář
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

29

Zásady správného používání výjimek

2/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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

30

Zásady správného používání výjimek

3/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í značky @throws
► 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.

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

31

Nejčastěji používané výjimky

1/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é

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

32

Nejčastěji používané výjimky

2/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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

33

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

35

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

36

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

37

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

38

Vaše jistota na trhu IT

Vnořené typy (nested, static inner)

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

40

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

41

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"), ;

Příklad 1: třída Směr8

TŘÍDY ===============================================
Statický
inicializační
blok
Deklarace
hodnot
Přepravka
pro
dočasné
uchování
int SMĚRŮ = 8;
inicializující
pole
a mapu
(veřejných
konstant)
hodnot zadaných
konstruktoru,
int MASKA = 7;
všechny
daného
typu
Map názvyKonstruktor
= je bude ukládá
než
možno
uložit
do přepravky,
new HashMap(
);
doparametry
mapySMĚRŮ*3
a příslušných
polí
private static final int[][] posun = new int[SMĚRŮ][2];
aby je bylo možno vyzvednout
private static final Směr8[] SMĚRY = values();
ve statickém inicializačním bloku

//== KONSTANTNÍ ATRIBUTY
public static final
private static final
private static final

Mapa pro odvození instance
static {
ze zadaného názvu
Instance si svá data nepamatují ve
for( Směr8 s : SMĚRY ) {
vlastních atributech, ale v polích,
posun[s.ordinal()][0] = s.přepravka.dx;
posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy tří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;

}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

42

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
}
VŠE – 05
43
Copyright © 2006, Rudolf Pecinovský

Vaše jistota na trhu IT

Vnitřní třídy (inner classes)

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

45

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();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

46

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

47

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

48

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

49

Vaše jistota na trhu IT

Anonymní třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

51

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
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

52

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 IPojmenovaný vytvoř(
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

final String název ) {
return new IPojmenovaný() {
String jméno;
{ jméno = název; }
public String getNázev() {
return jméno;
}
};
}
Lepší řešení
IPojmenovaný vytvoř( final String název ) {
return new IPojmenovaný() {
public String getNázev() {
return název;
}
};
}

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

53

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

54

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
●…

Instance anonymní tříd
je použita jako parametr

JButton tlačítko = new JButton( OK );
tlačítko.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
potvrzeno();
}
}
);
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

55

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
Thread t = new Thread( "Ukázka" ) {
public void run() { metoda(); }
};
t.start();
► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,
tj. v témže příkazu použít
new Thread( "Ukázka" ) {
public void run() { metoda(); }
}.start();

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

56

Použití 3: Funkční výčtové typy

2/3

► Instance funkčního
výčtového typy jsou
instancemi potomka
tohoto typu

public enum Operace {
PLUS {
public int proveď( int a, int b) {
return a + b;
}
► Z venku není dovnitř
},
potomků vidět, takže
MINUS {
nevím, jaké metody
public int proveď( int a, int b) {
deklarují =>
return a - b;
}
► Metody instancí
};
funkčních výčtových
typů musí být
public abstract proveď( int a, int b );
v rodiči deklarovány }
jako abstraktní – tím
se zviditelní

//...
Operace op = PLUS;
int výsledek = op.proveď( x, y );
//...
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

57

Použití 4: Vektory metod

3/3

public interface IOperace {
public int proveď( int a, int b );
}
IOperace[] op = {
new IOperace()
public int
},
new IOperace()
public int
}
};

{
proveď( int a, int b ) {

return a * b; }

{
proveď( int a, int b ) {

return a / b; }

Random rnd = new Random();
//...
int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);
//...

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

58

Vaše jistota na trhu IT

Pojmenované lokální třídy

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

60

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 );
}
}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

61

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

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

63

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))

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

64

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

65

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í

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

66

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á)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

67

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

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

68

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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

69

Příklad: Třídění nativní a modulo

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]
public class Modulo2 implements Comparable
Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,
{
private final int hodnota;
85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
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);
VŠE – 05
Copyright © 2006, Rudolf Pecinovský

70

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

71

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)

Copyright © 2006, Rudolf Pecinovský

VŠE – 05

72

Zdrojový kód metody max(Collection)
//Deklarace typových parametrů jsou zjednodušené
public static >
Kolekcí budeme
T max(Collection coll)
procházet pomocí
{
iterátoru
Iterator i = coll.iterator();
T candidate = i.next();

Připravíme si
kandidáta na maximum

while(i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;

}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

Procházíme zbytkem kolekce,
a je-li někdo větší než kandidát,
prohlásíme jej za lepšího kandidáta

73

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();

Je-li dodán komparátor,
připraví
si pokračuje
iterátor
Je-li
zadán
Pak
prázdný
a odkaz
kandidáta
najako
maximum
stejně
na komparátor,
minule,
zkusímejenom
verzi bez
s jinou
komparátoru
metodou

while(i.hasNext()) {
porovnání hodnot
T next = i.next();
if (comp.compare(next, candidate) > 0)
Verze bez komparátoru vyžaduje
candidate = next;
nativně porovnatelné objekty –
}
definuje si soukromé vnořené rozhraní,
return candidate;

na něž se pokusí instance přetypovat
}
private interface SelfComparable
extends Comparable {}
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

74

Vaše jistota na trhu IT

Děkuji za pozornost

►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600

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() {
VŠE – 05
Copyright © 2006, Rudolf Pecinovský
return new MůjIterator(
this );

77

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() { Protože je definována uvnitř třídy,
return (pořadí < f.prvky.size());
má přístup k soukromým složkám
jejích instancí
}
public E next() {
return f.prvky.get(
pořadí++
); –
Neplnohodnotná
implementace
}
volání metody způsobí chybu
Copyright © 2006, Rudolf Pecinovský

VŠE – 05

78

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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 12






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 13






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 14






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 15






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 16






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 17






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 18






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 19






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 20






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 21






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 22






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 23






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 24






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 25






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 26






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 27






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 28






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 29






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 30






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 31






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 32






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 33






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 34






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 35






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 36






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 37






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 38






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 39






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 40






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 41






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 42






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 43






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 44






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 45






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 46






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 47






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 48






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 49






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 50






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 51






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 52






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 53






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 54






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 55






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 56






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 57






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 58






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 59






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 60






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 61






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 62






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 63






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 64






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 65






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 66






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 67






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 68






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 69






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 70






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 71






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 72






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 73






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 74






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 75






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{ Vaše jistota na trhu ITInterní datovétypy a výjimkyRudolf Pecinovský Vaše jistota na trhu ITObsah s odkazy►Výjimky►Výjimky kontrolované a nekontrolované►Definice vlastních výjimek►Interní datové typy►Vnořené typy (nested, static inner)►Vnitřní třídy (inner classes)►Anonymní třídy►Pojmenované lokální třídy►Rozhraní Comparable a Comparator Vaše jistota na trhu ITVý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í 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íCopyright © 2006, Rudolf PecinovskýVŠE – 054 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émuz místa jeho vzniku do místa, kde bude problém řešenCopyright © 2006, Rudolf PecinovskýVŠE – 055 Postup při vyvolání výjimky1. 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řena3. 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ýšea nenarazí-li cestou nikde na své ošetření,zachytí ji virtuální stroj, který na standardní chybový výstupvypíše zprávu o vzniku výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 056 Systémová zpráva o vzniku výjimkyZprá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)Informace o místě, odkud byla volána metoda,která vyvolala metodu, v níž došlo k vyhození výjimkyInformace o místě, odkud byla volána metoda,v níž došlo k vyhození výjimkyÚplný název třídy včetně balíčkuCopyright © 2006, Rudolf PecinovskýNázev metodyVŠE – 05Název souboru sezdrojovým kódemČíslo řádku zdrojáku,kde došlo k výjimce7 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ímina případném vzniku výjimky► throws (hází)Uvození seznamu výjimek vyhazovaných danou metodouCopyright © 2006, Rudolf PecinovskýVŠE – 058 Vyvolání a ošetření výjimky v kódutry {//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}Copyright © 2006, Rudolf PecinovskýVŠE – 059 Náznak činnosti – řádný průběhnedojde k vyvolání výjimky= nedojde k chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0512 Náznak činnosti – ošetřený výjimkatry {příkaz1(); Při provádění metody příkaz2dojde k ošetřené chyběpříkaz2();příkaz3();Byla vyhozena výjimkatohoto typu nebo typu}některého z potomkůcatch ( xxxException e ) {příkazProOšetřeníChyby();}Ostatní bloky catchcatch (…..se přeskočífinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0513 Náznak činnosti – neošetřená výjimkaPři provádění metody příkaz2dojde k NEošetřené chybětry {příkaz1();příkaz2();příkaz3();}catch ( xxxException e ) {příkazProOšetřeníChyby();}Ošetření nebylo nalezeno =>catch (…..provede se blok finallya opouští se metodafinally {ukončovacíPříkazy();}dalšíPříkaz();Copyright © 2006, Rudolf PecinovskýVŠE – 0514 Vyvolání výjimkypublic 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;}}► 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ředatCopyright © 2006, Rudolf PecinovskýVŠE – 0515 Vaše jistota na trhu ITVýjimky kontrolované anekontrolované►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é Charakteristika► Výjimky, které jsou potomky třídy RuntimeExceptionnebo 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řipravena měl by na ně umět reagovatCopyright © 2006, Rudolf PecinovskýVŠE – 0517 Hierarchie výjimekCopyright © 2006, Rudolf PecinovskýVŠE – 0518 Pořadí výjimek v blocích catch► Třída NumberFormatExceptionje potomkem třídy RuntimeExceptiontry {Syntaktická chyba,......na druhý blok catch nikdy nedojde}catch (RuntimeException e) {.........}Obrácené pořadí bloků catchcatch (NumberFormatException e){vše vyřeší........try {}......}catch (NumberFormatException e) {.........}catch (RuntimeException e){........}Copyright © 2006, Rudolf PecinovskýVŠE – 0519 Metody generující výjimky► Java vyžaduje, aby programy, které používají metodyschopné 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}Copyright © 2006, Rudolf PecinovskýVŠE – 0520 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í posloupnostivedoucí k místu zavolání této metody► StackTraceElement[] getStackTrace()Vrátí uchované informace o volací posloupnosti dané výjimkyCopyright © 2006, Rudolf PecinovskýVŠE – 0521 Zřetězené výjimky► V některých situacích je vhodné v rámci ošetření výjimky vyvolatjinou 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í parametrodkaz 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 metodupublic Throwable getCause()► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimkanahrazena jinou, označována textem caused by:Copyright © 2006, Rudolf PecinovskýVŠE – 0522 Ukázka výpisu při zřetězení výjimekHighLevelException: MidLevelException: LowLevelExceptionat Junk.a(Junk.java:13)at Junk.main(Junk.java:4)Caused by: MidLevelException: LowLevelExceptionat Junk.c(Junk.java:23)at Junk.b(Junk.java:17)at Junk.a(Junk.java:11)... 1 moreCaused by: LowLevelExceptionat Junk.e(Junk.java:30)at Junk.d(Junk.java:27)at Junk.c(Junk.java:21)... 3 moreCopyright © 2006, Rudolf PecinovskýVŠE – 0523 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íš nedojdea 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šlozaměnit kontrolovanou výjimku za nekontrolovanoupublic void prevod( String s ) {try {prověř( s );} catch( Exception ex ) {throw new RuntimeException( " Neprověřeno! ", ex );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0524 Vaše jistota na trhu ITDefinice 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 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 Exceptionpřed nímž je naznačena podstata dané výjimky● IllegalArgumetnException● NoSuchMethodException● BadStringOperationExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0526 Příklad vlastní kontrolované výjimkypublic class VelkýPrůšvihExceptionextends 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0527 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ýjimkupublic void testVyhozeníVýjimky(){try {metodaKteráMáVyhoditVýjimku();} catch ( VelkýPrůšvihException vpe ) {return;}fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );}Copyright © 2006, Rudolf PecinovskýVŠE – 0528 Zásady správného používání výjimek1/2Neignorujtevýjimkytry {//Nějaký kód}catch(Exception e){}► 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ářCopyright © 2006, Rudolf PecinovskýVŠE – 0529 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ěžujea 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ýjimkyby měl být objekt v dobře definovaném stavuCopyright © 2006, Rudolf PecinovskýVŠE – 0530 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íchkomentářích pomocí značky @throws► 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.Copyright © 2006, Rudolf PecinovskýVŠE – 0531 Nejčastěji používané výjimky1/2► IllegalArgumentExceptionByla zadána nepovolená hodnota parametru● Např. chci nastavit zápornou velikost grafického tvaru► IllegalStateExceptionV 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► NullPointerExceptionByla vyvolána metoda instance, na níž ukazuje prázdný odkaz,nebo byl předán nepovolený prázdný odkaz v parametru► ArrayIndexOutOfBoundExceptionByly zadány špatné meze pole, buď záporné nebo moc velkéCopyright © 2006, Rudolf PecinovskýVŠE – 0532 Nejčastěji používané výjimky2/2► ConcurrentModificationExceptionV průběhu iterace byla změněna struktura kontejneru● Např. byl do kontejneru přidán prvek► NumberFormatExceptionJe 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► ClassCastExceptionPožadované přetypování není možné► UnsupportedOperationExceptionPožadovaná operace není podporována(např. chci přidat prvek do neměnného kontejneru)Copyright © 2006, Rudolf PecinovskýVŠE – 0533 Vaše jistota na trhu ITInterní 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 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 aimplementovat libovolné viditelné rozhraní► Jsou uvnitř svých vnějších typů,a proto vidí i na jejich soukromé (private) členyCopyright © 2006, Rudolf PecinovskýVŠE – 0535 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0536 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0537 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řídCopyright © 2006, Rudolf PecinovskýVŠE – 0538 Vaše jistota na trhu ITVnořené typy (nested, static inner) Charakteristika► Deklarovány s modifikátorem static(rozhraní static nepotřebují, protože jiná být nemohou)► Jsou to zcela obyčejné typyse 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0540 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řístupk soukromým atributům své vnější třídy► Pro rozhraní je občas vhodné definovat typickou implementacideklarovaný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ůmCopyright © 2006, Rudolf PecinovskýVŠE – 0541 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"), ;Příklad 1: třída Směr8TŘÍDY ===============================================StatickýinicializačníblokDeklaracehodnotPřepravkaprodočasnéuchováníint SMĚRŮ = 8;inicializujícípolea mapu(veřejnýchkonstant)hodnot zadanýchkonstruktoru,int MASKA = 7;všechnydanéhotypuMap























Slide 76






[email protected]









































































































































































































































































































































































































































































































































































































































































































































































































































názvyKonstruktor= je bude ukládánežmožnouložitdo přepravky,new HashMap





();doparametrymapySMĚRŮ*3a příslušnýchpolíprivate static final int[][] posun = new int[SMĚRŮ][2];aby je bylo možno vyzvednoutprivate static final Směr8[] SMĚRY = values();ve statickém inicializačním bloku//== KONSTANTNÍ ATRIBUTYpublic static finalprivate static finalprivate static finalMapa pro odvození instancestatic {ze zadaného názvuInstance si svá data nepamatují vefor( Směr8 s : SMĚRY ) {vlastních atributech, ale v polích,posun[s.ordinal()][0] = s.přepravka.dx;posun[s.ordinal()][1] = s.přepravka.dy; které jsou atributy třídyná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;}}Copyright © 2006, Rudolf PecinovskýVŠE – 0542 Příklad 2: IPosuvný.Adaptérpublic 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}VŠE – 0543Copyright © 2006, Rudolf Pecinovský Vaše jistota na trhu ITVnitřní třídy (inner classes) 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í atributobsahují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ší.thisCopyright © 2006, Rudolf PecinovskýVŠE – 0545 Konstrukce instance vnitřní třídy► V metodě instance● Odkaz na příslušnou instanci vnější třídypředá konstruktoru překladač (vezme this a předá je)► V metodě třídy● Odkaz na příslušnou instanci vnější třídumusí 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();Copyright © 2006, Rudolf PecinovskýVŠE – 0546 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řebadefinovat 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 konstruktorupředat v parametru odkaz na její instanci – složité, nepoužívatCopyright © 2006, Rudolf PecinovskýVŠE – 0547 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 vazbuna 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)Copyright © 2006, Rudolf PecinovskýVŠE – 0548 Příklad: Iterátorpublic class ItPole



















































































































































implements Iterable{private final Položka [] pole; //Pole položek typu Položkapublic 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0549 Vaše jistota na trhu ITAnonymní třídy Charakteristika► Jejich definice je součástí příkazu k vytvoření instance; je tona 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 × instanceCopyright © 2006, Rudolf PecinovskýVŠE – 0551 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ýchkonstruktorů 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 Objectnew Rodič(parametry) {//Definice potřebných metod}Copyright © 2006, Rudolf PecinovskýVŠE – 0552 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 IPojmenovaný vytvoř(proměnnouparametr,i on musí býtdefinovánjako konečný► Nemohou mítvlastníkonstruktor;je-li potřeba,používá semísto nějinicializačníblokfinal String název ) {return new IPojmenovaný() {String jméno;{ jméno = název; }public String getNázev() {return jméno;}};}Lepší řešeníIPojmenovaný vytvoř( final String název ) {return new IPojmenovaný() {public String getNázev() {return název;}};}Copyright © 2006, Rudolf PecinovskýVŠE – 0553 Omezení2/2►Nemohou definovat statické metody●Teoreticky je místo nich třebadefinovat 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žítkonstanty některého z blokův nichž je definice anonymní třídy zanořenaCopyright © 2006, Rudolf PecinovskýVŠE – 0554 Použití 1: Posluchači událostí1/3► Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instancepožadovaného typu● Posluchači událostí● Vlákna●…Instance anonymní třídje použita jako parametrJButton tlačítko = new JButton( OK );tlačítko.addActionListener(new ActionListener(){public void actionPerformed( ActionEvent ae ){potvrzeno();}});Copyright © 2006, Rudolf PecinovskýVŠE – 0555 Použití 2: Vytvoření ihned použitého objektu► Objekt vlákna (instance třídy Thread) monu nejprve vytvořita v dalším příkazu použítThread t = new Thread( "Ukázka" ) {public void run() { metoda(); }};t.start();► Stejně dobře ale mohu čerstvě vytvořený objekt ihned,tj. v témže příkazu použítnew Thread( "Ukázka" ) {public void run() { metoda(); }}.start();Copyright © 2006, Rudolf PecinovskýVŠE – 0556 Použití 3: Funkční výčtové typy2/3► Instance funkčníhovýčtového typy jsouinstancemi potomkatohoto typupublic enum Operace {PLUS {public int proveď( int a, int b) {return a + b;}► Z venku není dovnitř},potomků vidět, takžeMINUS {nevím, jaké metodypublic int proveď( int a, int b) {deklarují =>return a - b;}► Metody instancí};funkčních výčtovýchtypů musí býtpublic abstract proveď( int a, int b );v rodiči deklarovány }jako abstraktní – tímse zviditelní//...Operace op = PLUS;int výsledek = op.proveď( x, y );//...Copyright © 2006, Rudolf PecinovskýVŠE – 0557 Použití 4: Vektory metod3/3public interface IOperace {public int proveď( int a, int b );}IOperace[] op = {new IOperace()public int},new IOperace()public int}};{proveď( int a, int b ) {return a * b; }{proveď( int a, int b ) {return a / b; }Random rnd = new Random();//...int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y);//...Copyright © 2006, Rudolf PecinovskýVŠE – 0558 Vaše jistota na trhu ITPojmenované lokální třídy Charakteristika► Jsou velmi podobné anonymním třídám► Odchylky:● Mohou mít vlastní konstruktor● Mají jména, takže jejich instance mohu vytvářetna 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 konstantyCopyright © 2006, Rudolf PecinovskýVŠE – 0560 Příklad: Filtr souborůprivate static

























































































































































































































































































void najdiVeSlozce( File koren, Class predek, String balicek,Collection

>tridy ){// Filtr souboru k dalsi analyze - pousti jen class-souboryclass 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 );}}Copyright © 2006, Rudolf PecinovskýVŠE – 0561 Vaše jistota na trhu ITRozhraní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říkaz89–93 Typy s definovaným pořadím► Řada hodnotových objektových typů má definovanéporovnávání hodnot► Porovnatelnost hodnot instancí deklaruje třídaimplementací rozhraní java.lang.Comparable








































► Rozhraní vyžaduje implementaci jediné metodyint compareTo( T t )► Vracená hodnota:●<●=●>0 je-li this < t0 je-li this == t0 je-li this > tCopyright © 2006, Rudolf PecinovskýVŠE – 0563 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))Copyright © 2006, Rudolf PecinovskýVŠE – 0564 Nativní třídění polí a seznamů► K třídění polí slouží metodyjava.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ží metodajava.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á ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0565 Problémy související s tříděním► V různých fázích práce programu potřebuji tříditpodle 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ériumimplementované 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íCopyright © 2006, Rudolf PecinovskýVŠE – 0566 Rozhraní java.util.Comparator













































► Předchozí problémy lze řešit definicí třídyimplementující rozhraní java.util.Comparator

► Rozhraní Comparator
vyžaduje definici metodyint compare(T t1, T t2)► Vracená hodnota i požadavky na metodu jsou stejné jakou 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á)Copyright © 2006, Rudolf PecinovskýVŠE – 0567 Třídění polí a seznamů pomocí komparátoru► K třídění polí slouží metodyArrays.sort(T[] ta, Comparator c)Arrays.sort(T[] ta, int from, int to,Comparator c)► K třídění seznamů slouží metodaCoolections.sort(List














lt,Comparator c)► Instance komparátoru předaná jako parametrmusí umět vzájemně porovnatvšechny prvky v tříděném poli či seznamu;v opačném případě metoda vyvolá ClassCastExceptionCopyright © 2006, Rudolf PecinovskýVŠE – 0568 Příklad: Třídění nativní a modulopublic 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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský69 Příklad: Třídění nativní a moduloVý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]public class Modulo2 implements Comparable







































Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74,{private final int hodnota;85, 46, 56, 17, 47, 18, 88, 88, 79, 99]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() {Randomrnd = 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);VŠE – 05Copyright © 2006, Rudolf Pecinovský70 Další metody využívající porovnání1/2► K vyhledání prvku v setříděném polí slouží metodyArrays.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ží metodyCollections.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)Copyright © 2006, Rudolf PecinovskýVŠE – 0571 Další metody využívající porovnání2/2► K vyhledání největšího prvku v kolekci slouží metodyCollections.max(Collection












coll)Collections.max(Collection
coll,Comparator c)► K vyhledání nejmenšího prvku v kolekci slouží metodyCollections.max(Collection


coll)Collections.max(Collection
coll,Comparator c)Copyright © 2006, Rudolf PecinovskýVŠE – 0572 Zdrojový kód metody max(Collection








)//Deklarace typových parametrů jsou zjednodušenépublic static

>Kolekcí budemeT max(Collection

coll)procházet pomocí{iterátoruIterator



i = coll.iterator();T candidate = i.next();Připravíme sikandidáta na maximumwhile(i.hasNext()) {T next = i.next();if (next.compareTo(candidate) > 0)candidate = next;}return candidate;}Copyright © 2006, Rudolf PecinovskýVŠE – 05Procházíme zbytkem kolekce,a je-li někdo větší než kandidát,prohlásíme jej za lepšího kandidáta73 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();Je-li dodán komparátor,připravísi pokračujeiterátorJe-lizadánPakprázdnýa odkazkandidátanajakomaximumstejněna komparátor,minule,zkusímejenomverzi bezs jinoukomparátorumetodouwhile(i.hasNext()) {porovnání hodnotT next = i.next();if (comp.compare(next, candidate) > 0)Verze bez komparátoru vyžadujecandidate = next;nativně porovnatelné objekty –}definuje si soukromé vnořené rozhraní,return candidate;na něž se pokusí instance přetypovat}private interface SelfComparableextends Comparable





































{}Copyright © 2006, Rudolf PecinovskýVŠE – 0574 Vaše jistota na trhu ITDěkuji za pozornost►Rudolf Pecinovskýhttp://vyuka.pecinovsky.cz/vsemail: ICQ: 158 156 600 Příklad: Fronta – atributy a metodypublic class Fronta












[email protected]



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() {VŠE – 05Copyright © 2006, Rudolf Pecinovskýreturn new MůjIterator(this );77 Příklad: Fronta – vnořená třídaprivate class MůjIterator implements Iterator








{int pořadí = 0;Fronta


f;MůjIterator( Fronta
fronta ) {f = fronta;}public boolean hasNext() { Protože je definována uvnitř třídy,return (pořadí < f.prvky.size());má přístup k soukromým složkámjejích instancí}public E next() {return f.prvky.get(pořadí++); –Neplnohodnotnáimplementace}volání metody způsobí chybuCopyright © 2006, Rudolf PecinovskýVŠE – 0578 Příklad: Fronta – Testpublic 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 Frontafor( Integer fi : fronta )System.out.print( " " + fi );System.out.println("");}System.out.println("\nOdstraňujeme:");VŠE – 0579Copyrightfor(;;)© 2006, Rudolf Pecinovský{