Java pro geoinformatiky Tom´aˇs Bayer, Michal Schneider
Obsah 1 Neˇ z zaˇ cneme programovat...
7
1.1
Charakteristika Javy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.2
Pouˇzit´ı Javy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
1.3
Verze Javy
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.4
Vizu´ aln´ı v´ yvojov´ a prostˇred´ı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.5
Komponenty jazyka Java
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.6
Java a jej´ı specifika . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
2 Prvn´ı program v jazyce Java 2.1
2.2
14
Tvorba dokumentace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
2.1.1
Javadoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
Bal´ıˇcky v Javˇe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
2.2.1
18
Pr´ ace s bal´ıˇcky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 Datov´ e typy a promˇ enn´ e v Javˇ e 3.1
20
Z´akladn´ı datov´e typy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
3.1.1
Celoˇc´ıseln´e datov´e typy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
3.1.2
Znakov´ y typ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
3.1.3
ˇ ezcov´e konstanty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retˇ
22
3.1.4
Logick´ y datov´ y typ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
3.2
Re´aln´e datov´e typy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
3.3
Deklarace promˇenn´ ych . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
3.4
Pˇriˇrazov´ an´ı a pˇretypov´ an´ı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
3.5
Oper´ atory v Javˇe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
3.6
Matematick´e metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
3.7
Pr´ace se standardn´ım form´ atovan´ ym vstupem a v´ ystupem . . . . . . . . . . . . . . . . . . . .
28
3.7.1
29
Form´ atovan´ y v´ ystup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
OBSAH 3.7.2
Standardn´ı form´ atovan´ y vstup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
3.8
Pˇr´ıkazy v Javˇe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
3.9
Pole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
3.9.1
33
Kop´ırov´ an´ı pol´ı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 Vˇ etven´ı programu a opakov´ an´ı 4.1
4.2
Pˇrehled pˇr´ıkaz˚ u pro vˇetven´ı programu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
4.1.1
Konstrukce if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
4.1.2
Oper´ ator ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
4.1.3
Pˇr´ıkaz switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
Pˇrehled pˇr´ıkaz˚ u pro opakov´ an´ı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
4.2.1
Cyklus while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
4.2.2
Cyklus for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
4.2.3
Cyklus do while
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
4.2.4
Vnoˇren´e cykly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
4.2.5
Pˇr´ıkaz break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
4.2.6
Pˇr´ıkaz continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
5 Objekty, tˇ r´ıdy, metody 5.1
5.2
5.3
34
42
Metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
5.1.1
Metody tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43
5.1.2
Implicitn´ı a explicitn´ı konverze. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
5.1.3
Rekurzivn´ı metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
5.1.4
Pˇretˇeˇzov´ an´ı metod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
Tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
5.2.1
Deklarace tˇr´ıdy
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
5.2.2
Tˇelo tˇr´ıdy a pˇr´ıstupov´ a pr´ ava . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
Operace s tˇr´ıdami
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
5.3.1
Vytvoˇren´ı objektu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
5.3.2
Pˇr´ıstup k datov´ ym poloˇzk´ am . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
5.3.3
Ruˇsen´ı objekt˚ u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
5.3.4
Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
5.3.5
Odkaz this . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
5.3.6
Inicializace objektu jin´ ym objektem . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
5.3.7
Spuˇstˇen´ı metody v konstruktoru. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
5.3.8
Pr´ ace se statick´ ymi ˇcleny tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
5.3.9
Gettery a settery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
5.3.10 Pole objekt˚ u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
5.3.11 Pˇred´ av´ an´ı objekt˚ u jako parametr˚ u . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
OBSAH 6 Dˇ ediˇ cnost 6.1
61
Deklarace rodiˇcovsk´e a odvozen´e tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
61
6.1.1
Inicializace rodiˇcovsk´e tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
63
6.1.2
Inicializace odvozen´e tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
63
6.2
Pˇredefinov´ an´ı a pˇret´ıˇzen´ı metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
6.3
Fin´aln´ı metody a fin´ aln´ı tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
65
6.4
Abstraktn´ı metody a abstraktn´ı tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
6.5
Konverze mezi instancemi rodiˇcovsk´e a odvozen´e tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . .
67
6.6
Polymorfismus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
67
7 V´ yjimky
69
7.1
Druhy v´ yjimek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
7.2
Oˇsetˇren´ı v´ yjimek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
7.2.1
Oˇsetˇren´ı v´ yjimky propagac´ı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
7.2.2
Oˇsetˇren´ı v´ yjimky metodou chr´ anˇen´ ych blok˚ u . . . . . . . . . . . . . . . . . . . . . . .
72
7.2.3
Oˇsetˇren´ı v´ yjimky metodou chr´ anˇen´ ych blok˚ u a jej´ı pˇred´ an´ı v´ yˇse
. . . . . . . . . . . .
74
Tvorba vlastn´ıch v´ yjimek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
7.3
8 Rozhran´ı
78
8.1
Implementace jednoho rozhran´ı tˇr´ıdou . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78
8.2
Implementace v´ıce rozhran´ı tˇr´ıdou . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
8.3
Rozhran´ı a dˇediˇcnost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
82
8.4
Vnitˇrn´ı tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
82
8.4.1
Vnitˇrn´ı tˇr´ıdy a rozhran´ı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
84
8.4.2
Anonymn´ı vnitˇrn´ı tˇr´ıdy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
9 Dynamick´ e datov´ e struktury
87
9.1
Kontejnery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
88
9.2
Iter´ atory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
9.3
Rozhran´ı List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
9.3.1
ArrayList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
90
Rozhran´ı Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91
9.4.1
TreeSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
Rozhran´ı Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
9.5.1
93
9.4
9.5
TreeMap
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
OBSAH 10 Java, grafick´ e uˇ zivatelsk´ e rozhran´ı 10.1 Z´ akladn´ı komponenty a ud´ alosti
95 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
96
10.1.1 Rozdˇelen´ı komponent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
96
10.1.1.1 Top-level komponenty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
97
10.1.1.2 Kontejnerov´e komponenty
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
97
10.1.1.3 Z´ akladn´ı komponenty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
97
10.1.1.4 Needitovateln´e informaˇcn´ı komponenty . . . . . . . . . . . . . . . . . . . . .
98
10.1.1.5 Interaktivn´ı komponenty . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
10.1.2 Formul´ aˇre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
99
10.1.2.1 Nastaven´ı vzhledu komponent . . . . . . . . . . . . . . . . . . . . . . . . . . 101 10.1.2.2 Nastavov´ an´ı parametr˚ u grafick´eho rozhran´ı v konstruktoru jin´e tˇr´ıdy . . . . 102 10.1.2.3 Nastavov´ an´ı parametr˚ u grafick´eho rozhran´ı v konstruktoru t´eˇze tˇr´ıdy . . . . 102 10.1.3 Pˇrid´ av´ an´ı dalˇs´ıch komponent na formul´ aˇr . . . . . . . . . . . . . . . . . . . . . . . . . 104 10.1.4 Pr´ ace s ud´ alostmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 10.1.4.1 Oˇsetˇren´ı stejn´e ud´ alosti u v´ıce komponent . . . . . . . . . . . . . . . . . . . . 110 10.1.4.2 Nˇekolik posluchaˇc˚ u t´eˇze ud´ alosti . . . . . . . . . . . . . . . . . . . . . . . . . 112 10.1.5 Barvy, fonty, grafick´ y vzhled komponent . . . . . . . . . . . . . . . . . . . . . . . . . . 112 10.1.5.1 Barvy v Javˇe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 10.1.5.2 Fonty v Javˇe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 10.1.5.3 Z´ akladn´ı vlastnosti komponent . . . . . . . . . . . . . . . . . . . . . . . . . . 114 10.1.6 Layout managery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 10.1.6.1 FlowLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 10.1.6.2 GridLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 10.1.6.3 BorderLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 10.1.7 Modely v Javˇe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 10.1.8 Pˇrehled nejpouˇz´ıvanˇejˇs´ıch komponent . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 10.1.8.1 JLabel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 10.1.8.2 JButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 10.1.8.3 JCheckBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 10.1.8.4 JRadioButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 10.1.8.5 JTextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 10.1.8.6 JComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 10.1.8.7 JList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 10.1.8.8 JTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 10.1.8.9 Dialogov´ a okna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
OBSAH 10.1.8.10 JFileChooser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 10.1.8.11 JPanel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 10.1.9 Grafika . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 10.1.9.1 Z´ akladn´ı entity a jejich kresba . . . . . . . . . . . . . . . . . . . . . . . . . . 147 10.1.9.2 Pˇr´ıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 10.1.9.3 Pr´ ace s obr´ azky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 11 Aplety 11.1 Struktura appletu
161 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
ˇ 11.1.1 Zivotn´ ı cyklus appletu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 11.2 Tvorba appletu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 11.3 Spuˇstˇen´ı appletu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 11.3.1 Java archivy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 11.3.2 JAR soubory a aplety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 11.3.3 Applet viewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 11.3.4 Spouˇstˇen´ı appletu jako aplikace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 12 Java a datab´ aze
170
12.1 Komunikace s datab´azov´ ym syst´emem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 12.2 Z´ısk´av´ an´ı metadat o datab´ azi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 12.3 Vkl´ad´ an´ı dat do datab´ aze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 12.4 V´ ybˇer dat z datab´ aze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 12.5 Vymaz´ an´ı dat z datab´ aze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 12.6 Aktualizace dat v datab´ azi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 12.7 Dalˇs´ı pˇr´ıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 12.8 Z´ avˇer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
´ Uvod Tento materi´ al je vˇenov´ an z´ aklad˚ um programovac´ıho jazyku Java, kter´ y je velmi ˇcasto pouˇz´ıvan´ ym a popul´arn´ım n´astrojem pro v´ yvoj aplikac´ı vˇseho druhu. Nen´ı jazykem nejjednoduˇsˇs´ım, jeho pˇreloˇzen´ y k´ od nen´ı nejrychlejˇs´ı. Je to vˇsak velmi efektivn´ı, univerz´alnˇe pouˇziteln´ y, dynamicky se rozv´ıjej´ıc´ı jazyk vhodn´ y pro v´ yuku programov´ an´ı. Jedn´ a se o jazyk silnˇe typov´ y, objektovˇe orientovan´ y. Uˇzivatel se pˇri pr´aci s n´ım sezn´am´ı s technikou hierarchick´eho popisu probl´emu prostˇrednictv´ım objektov´eho modelu. Tento zp˚ usob myˇslen´ı mu poskytne zcela jin´ y pohled na ˇreˇsen´ı u ´loh a u ´ kol˚ u, se kter´ ymi se v geoinformatick´e praxi bˇeˇznˇe setk´av´a. Jednou z v´ yhod jazyka Java je jej´ı multiplatformita, tj. schopnost bˇeˇzet na prakticky libovoln´em operaˇcn´ım syst´emu. V souˇcasn´e dobˇe (jaro 2007) byl zdrojov´ y k´od jazyka Java firmou Sun otevˇren, pˇredstavuje tedy open source platformu pro v´ yvoj aplikac´ı. Materi´al nen´ı zamˇeˇren na konkr´etn´ı operaˇcn´ı syst´em ani konkr´etn´ı v´ yvojov´e prostˇred´ı. Nejedn´a se o ucelen´e d´ılo, novou uˇcebnici jazyka Java, takov´ ych je na souˇcasn´em trhu dostatek. Pˇredstavuje soubor pˇredn´aˇsek pˇreveden´ ych do elektronick´e formy, kter´ y student˚ um geoinformatiky poskytne prvn´ı sezn´amen´ı se svˇetem programov´an´ı. Z´ ajemc˚ um o hlubˇs´ı studium m˚ uˇzeme doporuˇcit zejm´ena [2] [3], kter´e se staly standardem, a vychovaly celou ˇradu v´ yborn´ ych program´ator˚ u. Z nich, a z mnoha jin´ ych, ˇcerp´a i tato publikace. Kapitoly 1-8, 10, 11 napsal Tom´ aˇs Bayer, kapitoly 9, 12 Michal Schneider. Vˇetˇsina pˇr´ıklad˚ u byla odladˇena ve v´ yvojov´em prostˇred´ı NetBeans firmy Sun. Pˇredem dˇekujeme za pˇr´ıpadn´e pˇripom´ınky, kter´e pˇrispˇej´ı ke zlepˇsen´ı tohoto textu zaslan´e na adresy:
[email protected] nebo
[email protected]. Praha, ˇr´ıjen 2007. Tom´aˇs Bayer Michal Schneider
Pro sazbu tohoto materi´ alu byl pouˇzit syst´em LATEX. Materi´al neproˇsel recenzn´ım ˇr´ızen´ım.
6
Kapitola 1
Neˇ z zaˇ cneme programovat... 1.1
Charakteristika Javy
Java patˇr´ı mezi pomˇernˇe nov´e programovac´ı jazyky. Uved’me nˇekter´a zaj´ımav´a fakta o tomto jazyku. Java vznikla v roce 1995 v laboratoˇr´ıch firmy Sun. P˚ uvodnˇe mˇela b´ yt pouˇzita pˇredevˇs´ım pro ovl´ad´an´ı inteligentn´ıch dom´ac´ıch spotˇrebiˇc˚ u jako ledniˇcek ˇci mikrovlnn´ ych trub. N´azev Java lze pˇreloˇzit jako k´ ava, resp. espreso. V logu nalezneme kouˇr´ıc´ı hrneˇcek s k´avou, jm´ena ˇrady komponent souvis´ı tak´e s k´ avou, napˇr. Java Beans (k´avov´e boby). Jazyk se mˇel jmenovat Oak, u ´dajnˇe podle dubu, kter´ y rostl tv˚ urci, J. Goslingovi, pod okny jeho domu. V souˇcasn´e dobˇe pouˇz´ıv´a Javu nˇekolik des´ıtek mili´on˚ u program´ ator˚ u po cel´em svˇetˇe. Javu lze ji charakterizovat nˇekolika n´ asleduj´ıc´ımi body: • Objektovˇe orientovan´y programovac´ı jazyk T´emˇeˇr vˇse v Javˇe je objektem. Stejnˇe jako C++, ze kter´eho vych´az´ı, umoˇzn ˇuje programov´an´ı bez nutnosti znalosti objektovˇe orientovan´eho programov´an´ı. Tento pˇr´ıstup vˇsak neumoˇzn ˇuje ˇreˇsen´ı sloˇzitˇejˇs´ıch probl´em˚ u a nen´ı doporuˇcov´ an. • Nez´ avislost na platformˇe Program napsan´ y v jazyce Java bˇeˇz´ı bez nutnosti prov´adˇet jak´ekoliv u ´pravy zdrojov´eho k´odu prakticky na vˇsech operaˇcn´ıch syst´emech. • Siln´ a typovost jazyka • Vyuˇzit´ı v prostˇred´ı Internetu Java umoˇzn ˇuje snadn´e pouˇz´ıv´ an´ı v prostˇred´ı s´ıtˇe Internet, nˇekdy b´ yv´a naz´ yv´ana ”jazykem Internetu”. • Integrace grafick´eho a s´ıt’ov´eho rozhran´ı, moˇznost pr´ ace s multim´edii Java obsahuje grafiku nez´ avislou na zaˇr´ızen´ı zabudovanou pˇr´ımo do jazyka. Grafick´e operace jsou standardizov´ any a poskytuj´ı stejn´e v´ ysledky bez ohledu na typ poˇc´ıtaˇce ˇci pouˇz´ıvan´ y operaˇcn´ı syst´em. • Zdarma Java je k dispozici vˇcetnˇe nˇekolika v´ yvojov´ ych prostˇred´ı zdarma. • Jednoduˇsˇs´ı syntaxe Z d˚ uvod˚ u zjednoduˇsen´ı pr´ ace v´ yvoj´ aˇre doˇslo i ke zjednoduˇsen´ı syntaxe Javy vzhledem k C++.
7
ˇ ZACNEME ˇ KAPITOLA 1. NEZ PROGRAMOVAT... • Vysok´y v´ykon Snadn´ a pr´ ace s objekty prostˇrednictv´ım tzv. garbage collectoru. • Bezpeˇcnost Odstranˇen´ı ˇrady potenci´ alnˇe nebezpeˇcn´ ych konstrukc´ı, kter´e b´ yvaj´ı zdrojem ˇcast´ ych a tˇeˇzko odhaliteln´ ych chyb.
1.2
Pouˇ zit´ı Javy
Java m´ a vˇsestrann´e pouˇzit´ı. D´ıky sv´e relativn´ı jednoduchosti je tak´e vhodn´ ym jazykem pro v´ yuku objektovˇe orientovan´eho programov´ an´ı. Java je vyuˇz´ıv´ ana zejm´ena pro tvorbu: • aplikac´ı ve formˇe samostatn´ ych program˚ u, toto pouˇzit´ı vˇsak nen´ı zcela typick´e. • applet˚ u, tj. kr´ atk´ ych program˚ u bˇeˇz´ıc´ıch v oknˇe webov´eho prohl´ıˇzeˇce. • servlet˚ u, tj. program˚ u bˇeˇz´ıc´ıch na serverech vytv´ aˇrej´ıc´ıch dynamick´e str´ anky. • distribuovan´ ych syst´em˚ u, tj. program˚ u skl´ adaj´ıc´ıch se z v´ıce ˇc´ ast´ı bˇeˇz´ıc´ıch souˇcasnˇe na vˇetˇs´ım mnoˇzstv´ı poˇc´ıtaˇc˚ u. • aplikac´ı pˇredstavuj´ıc´ı mezivrstvu pro komunikaci s datab´ azov´ ymi stroji ˇci s´ıt’ovou komunikaci. • aplikac´ı pro mobiln´ı ˇci telekomunikaˇcn´ı zaˇr´ızen´ı. Java m´ a vˇsak i sv´e nev´ yhody, kter´e se daj´ı shrnout do n´ asleduj´ıc´ıch bod˚ u: • Hardwarov´ a n´ aroˇcnost. D´ ana vestavˇenou kontrolou pr´ ace s pamˇet´ı, kter´ a je mnohem detailnˇejˇs´ı neˇz v C++. Doporuˇcen´ a HW konfigurace pˇredstavuje cca. 1GB RAM. • Rychl´ y v´ yvoj jazyka. V´ yvoj JDK je velmi rychl´ y, nˇekter´e funkce jsou “zastaral´e” p´ ar mˇes´ıc˚ u po vyd´an´ı JDK a v dalˇs´ı verzi kompletnˇe pˇrepracov´ any. V souˇcasn´ ych verz´ıch jsou jiˇz z´ akladn´ı funkce standardizov´ any. • Rozs´ ahlost Javy je souˇcasnˇe i jej´ı nev´ yhodou, disponuje ˇr´ adovˇe tis´ıci funkcemi a nutnost prostudov´an´ı znaˇcn´eho mnoˇzstv´ı literatury. • Sloˇzitˇejˇs´ı pr´ ace se standardn´ım vstupem/v´ ystupem. • Ponˇekud niˇzˇs´ı rychlost bˇehu program˚ u zp˚ usoben´ a t´ım, ˇze se nejedn´ a o jazyk kompilovan´ y (cca. 2x niˇzˇs´ı neˇz u C++). Prvn´ı verze byly aˇz 30 pomalejˇs´ı, s kaˇzdou dalˇs´ı novou verz´ı se tento rozd´ıl st´ır´ a. • D´elka z´apisu k´ odu pro realizaci standardn´ıch operac´ı je u Javy vˇetˇs´ı neˇz u jin´ ych programovac´ıch jazyk˚ u. V souˇcasn´e dobˇe se pomˇernˇe dynamicky rozv´ıj´ı prostˇred´ı .NET firmy Microsoft, konkr´etnˇe jazyk C#. Vyuˇz´ıv´a podobn´ y pˇr´ıstup jako Java, pro bˇeh program˚ u je nutno, aby na c´ılov´em zaˇr´ızen´ı byl pˇr´ıtomen virtu´ aln´ı stroj, tzv. .NET framework. Syntaxe jazyka C# je velmi podobn´ a syntaxi Javy. Prostˇred´ı .NET bylo portov´ano na jin´e operaˇcn´ı syst´emy v r´ amci projektu Mono. Dalˇs´ı informace lze nal´ezt na http://www.mono-project.org.
ˇ ZACNEME ˇ KAPITOLA 1. NEZ PROGRAMOVAT...
1.3
Verze Javy
Java je jazyk dynamicky se vyv´ıjej´ıc´ı. V souˇcasn´e dobˇe (2007) m´ ame k dispozici jiˇz jeho ˇsestou verzi. Verze Javy jsou oznaˇcov´ any bud’ desetinn´ ymi ˇc´ısly JDK 1.2, 1.3, 1.4 nebo Java 2, 3, 4; aktu´ alnˇe je dostupn´e JDK 6.0. Pro v´ yvoj aplikac´ı v jazyce Java je nutno m´ıt nainstalov´ ano prostˇred´ı JDK, tzv. Java Development Kit, pro bˇeh aplikac´ı prostˇred´ı JRE (Java Runtime Environment). Tato prostˇred´ı lze st´ ahnout ze str´ anek http: //www.sun.com/java. Rozd´ıly mezi verzemi spoˇc´ıvaj´ı pˇredevˇs´ım v kvalitnˇejˇs´ı implementaci knihoven, pˇrid´ av´ an´ı nov´ ych funkc´ı a komponent, napˇr. pro grafick´e ˇci datab´ azov´e rozhran´ı. Od Javy 1.2 bylo nahrazeno p˚ uvodn´ı grafick´e rozhran´ı AWT (Abstract Windows Toolkit) nov´ ym grafick´ ym rozhran´ım Swing.
1.4
Vizu´ aln´ı v´ yvojov´ a prostˇ red´ı
Java umoˇzn ˇuje vytv´ aˇren´ı klasick´ ych “okenn´ıch” aplikac´ı. Lze tak ˇcinit pˇr´ım´ ym z´ apisem zdrojov´eho k´ odu nebo ve speci´ aln´ıch n´ astroj´ıch naz´ yvan´ ych RAD (Rapid Application Development). Tyto n´astroje umoˇzn ˇ uj´ı prov´ adˇet vizu´ aln´ı n´ avrh aplikac´ı jejich sestavov´ an´ım z pˇredem pˇripraven´ ych vizu´aln´ıch komponent. Dˇeje se tak zpravidla pouh´ ym pˇretahov´ an´ım jednotliv´ ych grafick´ ych komponent (tlaˇc´ıtek, pˇrep´ınaˇc˚ u, dialog box˚ u,...) myˇs´ı s n´ asledn´ ym nastaven´ım vzhledov´ ych a funkˇcn´ıch parametr˚ u. Zdrojov´ y k´od k tˇemto akc´ım je generov´ an v´ yvojov´ ym prostˇred´ım automaticky. Tyto n´ astroje b´ yvaj´ı naz´ yv´ any tak´e GUI buildery. Upozornˇeme, ˇze takov´ y k´ od ˇcasto neb´ yv´ a tak efektivn´ı jako k´ od napsan´ y program´ atorem. C´ılem RAD n´astroj˚ u je usnadnˇen´ı vizu´ aln´ıho n´ avrhu aplikace, program´ ator m˚ uˇze uˇsetˇren´ y ˇcas vˇenovat na zlepˇsen´ı funkˇcnosti aplikace. Vizu´ aln´ı v´ yvojov´ a prostˇred´ı jsou k dispozici jak v komerˇcn´ıch, tak i bezplatn´ ych verz´ıch. Pˇrehled RAD n´ astroj˚ u: • Eclipse (http://www.eclipse.com): Nejˇcastˇeji pouˇz´ıvan´e vizu´ aln´ı v´ yvojov´e prostˇred´ı. K dispozici zdarma, nˇekter´e n´ astroje a funkce vˇsak pouze v placen´e verzi. • NetBeans (http://www.netbeans.org): P˚ uvodnˇe ˇcesk´e v´ yvojov´e prostˇred´ı vznikl´e na MFF UK, koupila ho firma Sun. Disponuje velmi kvalitn´ım layout managerem naz´ yvan´ ym Mattise. K dispozici i se vˇsemi doplˇ nky zdarma. • JBuilder (http://www.borland.com): V´ yvojov´e prostˇred´ı od firmy Borland, k dispozici zdarma. • IntelliJ IDEA (http://www.jetbrains.com): V souˇcasn´e dobˇe jedno z nejlepˇs´ıch v´ yvojov´ ych prostˇred´ı pro Javu. • Sun Java Studio (http://www.sun.com): N´ astroj pro v´ yvoj enterprise aplikac´ı zaloˇzen´ ych na jazyce Java.
1.5
Komponenty jazyka Java
Java je tvoˇrena tˇremi z´ akladn´ımi komponentami: • Programovac´ı jazyk Java
ˇ ZACNEME ˇ KAPITOLA 1. NEZ PROGRAMOVAT... • Javovsk´ y virtu´ aln´ı stroj (JVM) • Aplikaˇcn´ı rozhran´ı (API) Java se liˇs´ı od ostatn´ıch programovac´ıch jazyk˚ u pˇr´ıstupem, jak´ ym je program pˇrekl´ ad´ an a spouˇstˇen. Struˇcn´e vysvˇetlen´ı nalezneme v n´ asleduj´ıc´ıch odstavc´ıch. Java je jazyk leˇz´ıc´ı na rozhran´ı mezi kompilovan´ ymi a interpretovan´ ymi jazyky. U jazyk˚ u kompilovan´ ych je zdrojov´ y k´ od pˇreloˇzen do strojov´ ych instrukc´ı procesoru. Takov´ y k´od m˚ uˇze b´ yt n´ aslednˇe spuˇstˇen. U jazyk˚ u interpretovan´ ych je pˇreklad programu opakovanˇe prov´adˇen pˇri jeho spuˇstˇen´ı, aby program mohl vykon´ avat svoji funkci, je nutn´ a pˇr´ıtomnost tzv. interpretru, kter´ y prov´ ad´ı pˇreklad programu do strojov´eho k´ odu. Bajtov´ y k´ od. Zdrojov´ y k´ od programu pˇredstavovan´ y textov´ ym souborem s koncovkou *.JAVA je pˇreloˇzen do jazyka javovsk´eho virtu´ aln´ıho stroje ve formˇe tzv. bajtov´eho k´ odu. Bajtov´ y k´ od tvoˇren´ y souborem *.CLASS m˚ uˇze b´ yt spuˇstˇen pouze na virtu´ aln´ım poˇc´ıtaˇci pˇredstavovan´ ym JVM, nelze ho spustit pˇr´ımo na c´ılov´em poˇc´ıtaˇci. Bajtov´ y k´ od je tak nez´ avisl´ y na konkr´etn´ım hardwarov´em a softwarov´em vybaven´ı poˇc´ıtaˇce. Javovsk´ y virtu´ aln´ı stroj. JVM n´ aslednˇe prov´ ad´ı pˇrevod bajtov´eho k´ odu do strojov´eho k´ odu pˇr´ısluˇsn´eho procesoru, na kter´em je pr´ avˇe spuˇstˇen. Tomuto procesu ˇr´ık´ ame interpretace. Pˇreklad do bajtov´eho k´odu je proveden pouze jednou, interpretace pˇri kaˇzd´em spuˇstˇen´ı javovsk´eho programu. Upozorˇ nujeme, ˇze bajtov´ y k´ od lze zpˇetnˇe velmi snadno dekompilovat a z´ıskat v´ ypis zdrojov´eho k´ odu p˚ uvodn´ıho programu. Z tohoto d˚ uvodu by zdrojov´ y k´ od nemˇel obsahovat ˇz´ adn´e citliv´e informace jako napˇr. hesla, kter´ a jsou z nˇej snadno extrahovateln´ a. Aplikaˇ cn´ı rozhran´ı. Aplikaˇcn´ı rozhran´ı Javy (tzv. Java API) pˇredstavuje seznam knihoven a softwarov´ ych komponent, obsahuj´ıc´ı ˇradu n´ astroj˚ u pro pr´ aci se soubory, datab´ azemi, ˇretˇezci, grafikou, tˇr´ıd´ıc´ı algoritmy,... Jsou sdruˇzov´any do bal´ıˇck˚ u zvan´ ych packages. Jeden bal´ıˇcek obsahuje komponenty, kter´e spolu souvis´ı logicky ˇci t´ematicky. Tyto n´ astroje uˇsetˇr´ı program´ atorovi pr´ aci, protoˇze vyuˇz´ıv´ a jiˇz ovˇeˇren´e komponenty.
1.6
Java a jej´ı specifika
Java je zaloˇzena na jazyce C++, je vˇsak v´ıce objektovˇe orientovan´ ym programovac´ım jazykem neˇz C++. Lze prohl´asit, ˇze se jedn´ a o ˇcistokrevn´ y objektovˇe orientovan´ y programovac´ı jazyk. V Javˇe je (prakticky) vˇse objektem, tento jednotn´ y pˇr´ıstup umoˇzn ˇ uje jednoduˇsˇs´ı osvojen´ı z´ aklad˚ u jazyka a jeho pouˇz´ıv´ an´ı. Program´ator nemus´ı pˇrem´ yˇslet, zda pracuje ˇci nepracuje s objektem, vyuˇz´ıv´ a tedy jednotnou syntaxi. Java obsahuje pokroˇcil´e n´ astroje pro pr´ aci s objekty. Pokud nejsou nˇekter´e z n´ıˇze uveden´ ych pojm˚ u ˇcten´aˇri jasn´e, v dalˇs´ım textu se s nimi sezn´ am´ı podrobnˇeji. Pomˇernˇe ˇcasto budeme pouˇz´ıvat srovn´ an´ı Javy s jazykem ˇ aˇr, kter´ C++, kter´ y je povaˇzov´ an za “standard” v oblasti programov´ an´ı. Cten´ y tento jazyk nezn´ a, m˚ uˇze ˇ pozn´ amky pˇreskoˇcit. Cten´ aˇri znal´emu jazyka C++ pom˚ uˇze ulehˇcit pˇrechod na jazyk Java a vyvarovat se nˇekter´ ych z´akladn´ıch chyb plynouc´ıch z podobnosti implementace, ale rozd´ıln´e funkˇcnosti k´ odu. V dalˇs´ım textu budeme pro z´ apis zdrojov´eho k´ odu pouˇz´ıvat neproporcion´ aln´ı font. Identifik´ ator objektu. Identifik´ ator objektu pˇredstavuje odkaz na nˇej, jedn´ a se o obdobu ukazatel˚ u v pouˇz´ıvan´ ych napˇr. v jazyce C++. Z´ apis String o znamen´a vytvoˇren´ı odkazu o na objekt typu String. S vˇetˇsinou datov´ ych typ˚ u v Javˇe zach´ az´ıme “objektovˇe”, hovoˇr´ıme o tzv. objektov´ ych datov´ ych typech.
ˇ ZACNEME ˇ KAPITOLA 1. NEZ PROGRAMOVAT... Dynamick´ a tvorba objekt˚ u. Java zjednoduˇsuje pr´ aci s objekty, na rozd´ıl od C++ lze pracovat pouze s dynamicky vytvoˇren´ ymi objekty. Jsou vytv´ aˇreny prostˇrednictv´ım oper´ atoru new, nemus´ıme se vˇsak starat o jejich ruˇsen´ı. Garbage collector. Java disponuje automatickou spr´ avou pamˇeti, tento n´ astroj naz´ yv´ ame garbage collector. Star´ a se o automatick´e odstraˇ nov´ an´ı nepouˇz´ıvan´ ych objekt˚ u (tj. objekt˚ u, na kter´e jiˇz neexistuje odkaz). Odstraˇ nuje tak spoustu program´ atorsk´ ych chyb souvisej´ıc´ıch s ˇzivotnost´ı objekt˚ u. Okamˇzik smaz´ an´ı objektu nen´ı moˇzn´e ovlivnit, provede se, aˇz to syst´em uzn´ a s´ am za vhodn´e. Garbage collector lze vyvolat ruˇcnˇe pomoc´ı System.gc. Inicializace odkazu na objekt. V´ yˇse uveden´ y z´ apis nevede k vytvoˇren´ı samostatn´eho objektu. Pokud bychom se pokouˇseli s takov´ ym odkazem pracovat, dojde k v´ yjimce (tj. syst´emov´e chybˇe). Odkaz zat´ım nen´ı propojen na ˇz´ adn´ y objekt. Konstrukce o=new String("Ahoj"); vede k vytvoˇren´ı inicializovan´eho odkazu. Inicializace je provedena prostˇrednictv´ım ˇretˇezce typu String. Oba kroky lze spojit do jednoho. String o=new String("Ahoj"); Plat´ı z´ asada: pokud vytvoˇr´ıme odkaz, zpravidla k nˇemu vytv´ aˇr´ıme i objekt. V Javˇe lze v´ yˇse uvedenou konstrukci zapsat jednoduˇsˇs´ı formou. String objekt="Ahoj"; V´ ysledek t´eto operace je stejn´ y, neilustruje vˇsak tak n´ azornˇe pr´ aci s objekty. Primitivn´ı datov´ e typy. V Javˇe existuj´ı tzv. primitivn´ı datov´e typy. Pˇredstavuj´ı speci´ aln´ı skupinu datov´ ych typ˚ u, se kter´ ymi se zach´ az´ı ”neobjektovˇe”. Pouˇz´ıvaj´ı se v pˇr´ıpadˇe, kdy by byl objektov´ y pˇr´ıstup neefektivn´ı, napˇr. pˇri pr´ aci s bˇeˇzn´ ymi promˇenn´ ymi; Java v tomto pˇr´ıpadˇe kop´ıruje pˇr´ıstup jazyka C++. Takov´e promˇenn´e vytv´ aˇr´ıme jako tzv. statick´e promˇenn´e, maj´ı nˇekter´e speci´ aln´ı vlastnosti, se kter´ ymi se sezn´am´ıme v dalˇs´ım textu. Ke kaˇzd´emu primitivn´ımu datov´emu typu existuje jeho objektov´ a varianta. Kromˇe vlastnost´ı se liˇs´ı i z´ apisem, n´ azev primitivn´ı varianty zaˇc´ın´ a mal´ ym p´ısmenem, n´ azev objektov´e velk´ ym p´ısmenem, viz. tab. 1.1. Primitivn´ı typ boolean char byte short int long float double
Objektov´ y typ Boolean Char Byte Short Integer Long Float Double
Velikost 8b 8b 16b 32b 64b 32b 64b
Tabulka 1.1: Primitivn´ı a objektov´e datov´e typy v Javˇe.
ˇ ZACNEME ˇ KAPITOLA 1. NEZ PROGRAMOVAT... Velikost datov´ ych typ˚ u. Kaˇzd´ y datov´ y typ m´ a v Javˇe na r˚ uzn´ ych poˇc´ıtaˇc´ıch s r˚ uzn´ ymi operaˇcn´ımi syst´emy vˇzdy stejnou velikost, Java je tedy na rozd´ıl od ostatn´ıch programovac´ıch jazyk˚ u pˇrenositeln´a mezi r˚ uzn´ ymi platformami. Pole v Javˇ e. Pouˇz´ıv´ an´ı pol´ı v Javˇe je mnohem bezpeˇcnˇejˇs´ı neˇz v C++, nejedn´ a se totiˇz o pouh´e pamˇet’ov´e bloky. Nem˚ uˇze doj´ıt k situaci, kdy pˇri pr´ aci s polem pˇres´ ahneme index pole. Kontrola indexu pole je zaˇclenˇena pˇr´ımo do jazyka Java za cenu drobn´eho zat´ıˇzen´ı pamˇeti. Pˇri vytvoˇren´ı pole je zaruˇcena inicializace jeho jednotliv´ ych prvk˚ u. Lze vytv´ aˇret pole primitivn´ıch i objektov´ ych datov´ ych typ˚ u. Obor platnosti primitivn´ıch datov´ ych typ˚ u. U Javy jsou drobn´e rozd´ıly pˇri urˇcov´ an´ı platnosti objekt˚ u. V Javˇe neexistuje moˇznost definice stejn´e promˇenn´e ve vnoˇren´em bloku jako v nadˇrazen´em bloku. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad. { int a=10; int b=20; //k dispozici promenne a, b { double c=30.0; //k dispozici promenne a, b, c { double d=40.0; //k dispozi promenne a, b, c, d int a=50; //nelze } // k dispozici promenne a, b, c } //k dispozici promenne a, b } ˇ Obor platnosti dynamick´ ych datov´ ych typ˚ u. Zivotnost dynamick´ ych datov´ ych typ˚ u je jin´ a neˇz v pˇr´ıpadˇe primitivn´ıch datov´ ych typ˚ u. Objekt z˚ ust´ av´ a v pamˇeti i po ukonˇcen´ı rozsahu platnosti. { String objekt=new String("Ahoj"); }//konec oboru platnosti K tomuto objektu se vˇsak jiˇz nen´ı moˇzno ˇz´ adn´ ym zp˚ usobem dostat, protoˇze odkaz je po ukonˇcen´ı bloku mimo rozsah platnosti. Takov´e objekty jsou ruˇseny prostˇrednictv´ım garbage collectoru. Ten hled´ a, zda na objekt vytvoˇren´ y prostˇrednictv´ım oper´ atoru new existuje jeˇstˇe nˇejak´ a vazba prostˇrednictv´ım odkazu. Pokud neexistuje, je objekt zruˇsen. Datov´ y typ boolean char byte short int long float double
Hodnota false null 0 0 0 0L 0.0 0.0
Tabulka 1.2: Pˇrehled datov´ych typ˚ u a jejich inicializace
ˇ ZACNEME ˇ KAPITOLA 1. NEZ PROGRAMOVAT... Implicitn´ı hodnoty primitivn´ıch datov´ ych typ˚ u. Pˇri vytvoˇren´ı promˇenn´e jako datov´e poloˇzky tˇr´ıdy doch´ az´ı k pˇriˇrazen´ı v´ ychoz´ı hodnoty, i kdyˇz promˇenn´ a zat´ım nebyla inicializov´ ana. S t´ımto pˇr´ıstupem se v jazyce C++ nesetk´ ame. Kaˇzd´ a datov´ a poloˇzka tˇr´ıdy je pˇri sv´em vytvoˇren´ı automaticky inicializov´ana. Inicializace se net´ yk´ a promˇenn´ ych, kter´e nejsou datov´ ymi poloˇzkami tˇr´ıdy. Pokud neprovedeme inicializaci takov´e promˇenn´e, Java n´ as na rozd´ıl od jazyka C++ na tuto chybu upozorn´ı a takov´ y krok oznaˇc´ı jako chybu. int x; x++;//chyba, promenna nebyla inicializovana
Kapitola 2
Prvn´ı program v jazyce Java V t´eto kapitole vytvoˇr´ıme jednoduch´ y program v jazyce Java, pˇreloˇz´ıme ho do spustiteln´eho tvaru a vygenerujeme k nˇemu n´ apovˇedu ve form´ atu HTML. Sezn´am´ıme se se syntax´ı jazyka Java, z´aklady pr´ace s JVM a jeho konfigurac´ı. Volba editoru. Ot´ azkou je, jak´ y vˇsak zvolit editor pro z´apis zdrojov´eho k´odu? Lze pouˇz´ıt libovoln´ y editor pracuj´ıc´ı s ASCII k´ odem. Pro tyto u ´ˇcely se pod operaˇcn´ım syst´emem Windows hod´ı napˇr. Pozn´amkov´ y blok, pod operaˇcn´ım syst´emem Linux napˇr. gEdit. Nelze pouˇz´ıt klasick´ y textov´ y editor jako Word ˇci Writer, do textu jsou vkl´ ad´ any dodateˇcn´e informace o form´atov´an´ı. Z´ apis zdrojov´ eho k´ odu. N´azev souboru se zdrojov´ ym k´odem v Javˇe mus´ı b´ yt totoˇzn´ y s jm´enem tˇr´ıdy a to vˇcetnˇe velk´ ych i mal´ ych p´ısmen. Vytvoˇr´ıme nov´ y dokument s n´azvem Pokus.java, do kter´eho zap´ıˇseme n´asleduj´ıc´ı text. public class Pokus { public static void main(String [] args) { System.out.println("Tohle je muj"); System.out.println("prvni program v Jave"); } } A m´ame hotov´ y prvn´ı program v jazyce Java. Pˇ reklad programu. Program n´ aslednˇe pˇreloˇz´ıme do bajtov´eho k´odu. Pouˇzijeme k tomu vestavˇen´ y pˇrekladaˇc javac, kter´ y se pro verzi JDK 6.0 nach´az´ı pod operaˇcn´ım syst´emem Windows v n´asleduj´ıc´ı sloˇzce: C:\Progra~1\Java\jdk1.6.0\bin\javac.exe. Pro operaˇcn´ı syst´em Linux ho nalezneme zpravidla v adres´aˇri /etc/lib/jvm/java-6-sun-1.6.0.00/bin. Pˇredpokl´ad´ame, ˇze se soubor Pokus.java nach´az´ı v adres´aˇri totoˇzn´em s pracovn´ım adres´aˇrem, napˇr. ve sloˇzce C:\Dokumenty. Do pˇr´ıkazov´eho ˇr´ adku zadejme n´asleduj´ıc´ı pˇr´ıkaz: javac Pokus.java
14
KAPITOLA 2. PRVN´I PROGRAM V JAZYCE JAVA Pˇr´ıponu .java nen´ı moˇzn´e vynechat. Pokud se objevilo hl´ aˇsen´ı C:\>javac javac nen´ ı n´ azvem vnitˇ rn´ ıho ani vnˇ ejˇ s´ ıho pˇ r´ ıkazu, spustiteln´ eho programu nebo d´ avkov´ eho souboru. znamen´ a to, ˇze syst´em nezn´ a cestu k souboru javac. Lze ji nastavit pomoc´ı promˇenn´e PATH. Postup nastaven´ı se liˇs´ı pro jednotliv´e OS. Pro operaˇcn´ı syst´em WindoswXP tak m˚ uˇzeme uˇcinit v menu Start/Nastaven´ı/Ovl´adac´ı Panely/Syst´em/Upˇresnit/Promˇenn´e prostˇred´ı. Do promˇenn´e PATH pˇrid´ ame cestu k pˇr´ısluˇsn´emu adres´aˇri. Pokud m´ ame jinou verzi JDK popˇr. je JDK nainstalov´ ano v jin´e sloˇzce, uprav´ıme cestu dle potˇreby.
Obr´ azek 2.1: Konfigurace promˇenn´e PATH. Nechceme -li konfigurovat promˇennou PATH, m˚ uˇzeme cestu k souboru javac specifikovat v pˇr´ıkazov´e ˇr´adce. C:\Dokumenty> C:\Progra~1\Java\jdk1.6.0\bin\javac Pokus.java Pokud je JDK spr´ avnˇe nainstalov´ ano, vznikne ve stejn´e sloˇzce soubor s n´ azvem Pokus.class obsahuj´ıc´ı bajtov´ y k´od. Jestliˇze se objev´ı v´ ypis: javac: Invalid argument: Pokus pak jsme zˇrejmˇe zapomnˇeli zadat koncovku java. Zmˇen ˇte n´ azev tˇr´ıdy z Pokus na pokus a pokuste se program pˇreloˇzit. Podaˇr´ı se V´ am to? Spuˇ stˇ en´ı programu. Spuˇstˇen´ı programu provedeme pˇr´ıkazem: javac Pokus popˇr. se specifikac´ı cesty: C:\Progra~1\Java\jdk1.6.0\bin\java Pokus T´ımto zp˚ usobem vol´ ame interpretr jazyku Java a pˇred´ av´ ame mu jako parametr soubor Pokus.class. V pˇr´ıkazov´e ˇr´adce vˇsak nesm´ıme uv´est pˇr´ıponu .class, program si j´ı dopln´ı s´ am. Opˇet mus´ıme dodrˇzovat velk´ a a mal´a p´ısmena. Jestliˇze nem´ ame konfigurovanou promˇennou PATH, pracovn´ı adres´ aˇr pˇredpokl´ad´ame totoˇzn´ y s adres´ aˇrem, ve kter´em jsou uloˇzeny zdrojov´ y i pˇreloˇzen´ y soubor. Pokud jsme byli u ´spˇeˇsn´ı, v textov´e konzoli se objev´ı v´ ypis: Tohle je muj prvni program v Jave
KAPITOLA 2. PRVN´I PROGRAM V JAZYCE JAVA Jestliˇze se objev´ı podobn´ y v´ ypis: c:\Program Files\Java\jdk1.6.0\bin>javac Pokus.java Pokus.java:5: cannot find symbol symbol : class Strings location: class Pokus public static void main(Strings [] args) ^ Pokus.java:9: cannot find symbol symbol : method pritln(java.lang.String) location: class java.io.PrintStream System.out.pritln("Tohle je muj"); ^ 2 errors pak jsme zˇrejmˇe zdrojov´ y k´ od ˇspatnˇe opsali a doˇslo k syntaktick´e chybˇe. V tomto pˇr´ıpadˇe bylo m´ısto spr´avn´eho String pouˇzito Strings a m´ısto println pouˇzito pritln. Pozn´ amka: Zad´ av´ an´ı u ´pln´e cesty k soubor˚ um se zdrojov´ ym k´ odem nemus´ı b´ yt vˇzdy pohodln´e. Je proto moˇzn´e nastavit syst´emovou promˇennou CLASSPATH tak, aby obsahovala cesty k pˇr´ısluˇsn´ ym adres´ aˇr˚ um. Postup nastaven´ı se liˇs´ı pro jednotliv´e OS. Pro operaˇcn´ı syst´em Windosw XP tak lze uˇcinit v menu Start/Nastaven´ı/ Ovl´ adac´ı Panely/Syst´em/Upˇresnit/Promˇenn´e prostˇred´ı, je analogick´ y nastaven´ı promˇenn´e PATH. Program rozebereme podrobnˇe na jin´em m´ıstˇe, vˇsimnˇeme si analogie s programovac´ım jazykem C++. Rozd´ılem je fakt, ˇze kaˇzd´ y “v´ ykonn´ y k´ od” mus´ı b´ yt v Javˇe um´ıstˇen uvnitˇr tˇr´ıdy, kter´ a jej obaluje.
2.1
Tvorba dokumentace
Java obsahuje elegantn´ı n´ astroj pro vytv´ aˇren´ı vlastn´ı dokumentace. S jeho pomoc´ı m˚ uˇzeme automaticky generovat dokumentaci k jednotliv´ ym tˇr´ıd´ am, promˇenn´ym ˇci metod´ am. V´ ysledn´ a dokumentace je ve form´atu HTML soubor˚ u. Koment´ aˇ re. Pod´ıvejme se, jak´ ym zp˚ usobem jsou v Javˇe implementov´ any koment´ aˇre. Jedn´ a se o analogii s jazykem C++. // Toto je jednoradkovy komentar /* Toto je viceradkovy komentar */ Kromˇe tˇechto koment´ aˇr˚ u existuj´ı i tzv. dokumentaˇcn´ı koment´ aˇre. Ty jsou uvozeny znaky /** a zakonˇceny znaky */. Na poˇc´ atku kaˇzd´eho ˇr´ adku se nach´ az´ı hvˇezdiˇcky, kter´e jsou vˇsak ignorov´ any. /** Toto je * dokumentacni viceradkovy * komentar */ Z tˇechto dokumentaˇcn´ıch koment´ aˇr˚ u mohou b´ yt vygenerov´ any automaticky soubory s dokumentac´ı. Koment´ aˇre vˇsak mus´ı b´ yt um´ıstˇeny bezprostˇrednˇe pˇred definic´ı tˇr´ıdy, promˇenn´e ˇci metody, v opaˇcn´em pˇr´ıpadˇe budou ignorov´ any.
KAPITOLA 2. PRVN´I PROGRAM V JAZYCE JAVA /** Vzorova trida pokus */ public class Pokus { /** Promenna a */ private int a; /** Metoda main, ktera napise dve radky */ public static void main(String []args) { System.out.println("Tohle je muj"); System.out.println("prvni program v Jave"); } }
2.1.1
Javadoc
Pro vytv´ aˇren´ı dokumentace slouˇz´ı n´ astroj javadoc, kter´ y se nach´ az´ı v JDK 1.6 v n´ asleduj´ıc´ı sloˇzce C:\Progra~1\ Java\jdk1.6.0\bin\. resp /etc/lib/ jvm/java-6-sun-1.6.0.00/bin. Tvorbu dokumentace spust´ıme, za pˇredpokladu, ˇze jsme provedli nastaven´ı promˇenn´e ClASS, pˇr´ıkazem javadoc Pokus.java V opaˇcn´em pˇr´ıpadˇe je nutno zadat celou cestu. Stejnˇe jako pˇri pˇrekladu mus´ıme uv´est jm´eno souboru vˇcetnˇe koncovky. Ve sloˇzce vznikne jeˇstˇe spousta dalˇs´ıch soubor˚ u, v´ ysledkem je soubor s n´ azvem Pokus.html, kter´ y je um´ıstˇen ve stejn´e sloˇzce jako soubor se zdrojov´ ym k´ odem. Do dokumentaˇcn´ıch koment´ aˇr˚ u lze vkl´ adat nˇekter´e speci´ aln´ı znaky. Uved’me struˇcnˇe nˇekter´e nejˇcastˇeji pouˇz´ıvan´e. HTML tagy umoˇzn ˇuj´ı do dokumentaˇcn´ıch koment´ aˇr˚ u vkl´ adat k´ od ve form´ atu HTML. C´ılem je zlepˇsen´e form´ atov´ an´ı k´ odu pomoc´ı kurz´ıvy ˇci tuˇcn´eho ˇrezu p´ısma. Tag pro tuˇcn´ y ˇrez p´ısma se vkl´ ad´ a do koment´aˇre posloupnost´ı znak˚ u
, mezi nimi n´ asleduje zv´ yraznˇen´ y text, ukonˇcuje se posloupnost znak˚ u . Podobn´ ym zp˚ usobem je moˇzno vytvoˇrit i sklonˇen´ y text, pouˇzijeme k tomu tagy
a .Pod´ıvejme se na n´ asleduj´ıc´ı k´ od, kdy text “ktera napise” bude vys´ azen tuˇcnˇe. /** Metoda main,
ktera napise dve radky */ Speci´ aln´ı pˇ r´ıkazy jdou do dokumentaˇcn´ıch koment´ aˇr˚ u vkl´ adat zad´ an´ım znaku @. Pˇr´ıkaz @see slouˇz´ı k vytv´ aˇren´ı odkaz˚ u na dokumentaci jin´ ych tˇr´ıd, pˇr´ıkaz @version informaci o verzi programu, @author informace o autorovi. /** Dokumentace k programu * @see Pokus //odkaz na nazev tridy * @version 2.0 //informace o verzi * @author Novak //informace o autorovi. */
2.2
Bal´ıˇ cky v Javˇ e
Vzhledem k tomu, ˇze jm´ena soubor˚ u pˇredstavuj´ı n´ azvy tˇr´ıd, nen´ı moˇzn´e m´ıt v jedn´e sloˇzce stejnˇe pojmenovan´e tˇr´ıdy prov´ adˇej´ıc´ı napˇr. r˚ uznou ˇcinnost. Pokud chceme pojmenovat dvˇe r˚ uzn´e tˇr´ıdy stejnˇe, Java umoˇzn ˇ uje
KAPITOLA 2. PRVN´I PROGRAM V JAZYCE JAVA vyuˇz´ıt tzv. bal´ıˇcky (packages). Bal´ıˇcky pˇredstavuj´ı obdobu jmenn´ ych prostor˚ u (namespace) v C++. Bal´ıˇcek je fyzicky uloˇzen v adres´ aˇri. M˚ uˇze obsahovat i podbal´ıˇcky, kter´e se budou nach´ azet v podadres´ aˇr´ıch adres´aˇre. Jm´eno bal´ıˇcku je tvoˇreno cestou k soubor˚ um se tˇr´ıdami v nˇem obsaˇzen´ ym. Nezapisuje se vˇsak pomoc´ı zpˇetn´ ych lom´ıtek, adres´ aˇre jsou oddˇeleny teˇckou. M´ ame-li v adres´ aˇri Pokus bal´ıˇcek s n´ azvem Balik, ve kter´em se nach´ az´ı soubor Pokus.class, lze cestu k tomuto souboru zapsat ve tvaru Balik.Pokus Pˇri n´ avrhu Javy se vytvoˇril syst´em pojmenov´ an´ı bal´ıˇck˚ u takov´ y, aby byl v r´ amci cel´eho svˇeta jednoznaˇcn´ y. N´ azev bal´ıˇcku by mˇel vych´ azet z n´ azvu internetov´ ych dom´en “v opaˇcn´em” poˇrad´ı. Bal´ık Balik nach´ azej´ıc´ı se v dom´enˇe moje.cz bude m´ıt dle t´eto konvence n´ azev cz.moje.balik. V praxi se vˇsak tento pˇr´ıstup ne vˇzdy dodrˇzuje.
2.2.1
Pr´ ace s bal´ıˇ cky
Pokud chceme nˇejakou tˇr´ıdu pˇridat do bal´ıˇcku, uvedeme tuto informaci do prvn´ıho ˇr´ adku zdrojov´eho k´odu pˇr´ıkazem package nazev_baliku; Pokud bychom chtˇeli n´ ami vytvoˇrenou tˇr´ıdu Pokus pˇridat do bal´ıˇcku balik, vypadal by z´ apis zdrojov´eho k´ odu takto: package balik; public class Pokus { public static void main(String [] args) { System.out.println("Tohle je muj"); System.out.println("prvni program v Jave"); } } Kompilaci provedeme stejn´ ym zp˚ usobem jako v pˇredchoz´ım pˇr´ıpadˇe. Soubor Pokus.class um´ıst´ıme do adres´ aˇre balik. Pokud tento soubor chceme spustit, uˇcin´ıme tak jm´enem bal´ıku a jm´enem tˇr´ıdy: balik.Pokus. C:\Progra~1\Java\jdk1.6.0\bin\java balik.Pokus Uveden´ y postup naz´ yv´ ame kvalifikac´ı tˇ r´ıdy jm´enem bal´ıku. Pokud bychom chtˇeli tento bal´ıˇcek pouˇz´ıt v jin´em programu, museli bychom pˇr´ısluˇsnou tˇr´ıdu zapsat s uveden´ım kvalifikace bal´ıku. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad. Vytvoˇrme program Pokus2, ve kter´em budeme cht´ıt pouˇz´ıt instanci tˇr´ıdy Pokus. Na tˇr´ıdu Pokus se budeme muset odk´ azat za pouˇzit´ı kvalifikace. public class Pokus2 { public static void main(String [] args) { balik.Pokus objekt=new balik.Pokus(); } }
KAPITOLA 2. PRVN´I PROGRAM V JAZYCE JAVA Tento zp˚ usob pr´ ace je nepohodln´ y, n´ azev tˇr´ıdy s kvalifikac´ı m˚ uˇze b´ yt nˇekdy znaˇcnˇe dlouh´ y, zvl´ aˇstˇe u sloˇzitˇejˇs´ıch struktur bal´ıˇck˚ u. Pomoc´ı pˇr´ıkazu import s uveden´ım n´ azvu bal´ıˇcku ho m˚ uˇzeme “pˇripojit” a pˇri pr´aci s n´ım vynechat kvalifikaci. import balik; public class Pokus2 { public static void main(String [] args) { Pokus objekt=new Pokus(); } } Obsahuje-li bal´ıˇcek nˇejak´e podbal´ıˇcky, lze pro jejich zpˇr´ıstupnˇen´ı pouˇz´ıt z´ astupn´ y symbol *. V n´ asleduj´ıc´ım pˇr´ıkladu m´a bal´ıˇcek s n´ azvem balik dva podbal´ıˇcky: balicek1 a balicek2. Lze ps´ at import balik.balicek1; import balik.balicek2; Nebo vyuˇz´ıt z´ astupn´ y znak * a ps´ at import balik.*; Coˇz znamen´ a v pˇrenesen´em smyslu: pˇripoj vˇsechny podbal´ıˇcky bal´ıˇcku balik. Pr´ ace s bal´ıˇcky je typick´a u vˇetˇs´ıch projekt˚ u, pom´ ah´ a vytvoˇrit pˇrehlednou hierearchickou strukturu zdrojov´eho k´ odu. V t´eto kapitole jsme se struˇcnˇe sezn´ amili s vlastnostmi jazyku Java, uk´ azali si zp˚ usob, jak´ ym lze ps´at jednoduch´e programy, vytv´ aˇret dokumentaci k nim a vysvˇetlili si z´ akladn´ı operace s bal´ıˇcky. V n´ asleduj´ıc´ıch kapitol´ ach se s jazykem Java sezn´ am´ıme podrobnˇeji.
Kapitola 3
Datov´ e typy a promˇ enn´ e v Javˇ e Java je jazyk relativnˇe jednoduch´ y, jeho j´ adro obsahuje cca. 40 z´akladn´ıch pˇr´ıkaz˚ u. Velmi rozs´ahl´e je vˇsak API jazyka Java, kter´e skr´ yv´ a stovky pˇr´ıkaz˚ u. I pˇres v´ yˇse zm´ınˇen´ y fakt je struktura jazyka logick´a a umoˇzn´ı zaˇc´ateˇcn´ıkovi pomˇernˇe rychlou orientaci v problematice a snadn´e zvl´adnut´ı z´aklad˚ u programov´an´ı. Java pracuje se z´akladn´ımi (tj. primitivn´ımi) datov´ ymi typy a s objektov´ ymi datov´ ymi typy. Pˇripomeˇ nme, ˇze oznaˇcen´ı identifik´ator˚ u z´akladn´ıch datov´ ych typ˚ u zaˇc´ın´ a mal´ ym p´ısmenem, oznaˇcen´ı identifik´ator˚ u objektov´ ych datov´ ych typ˚ u velk´ ym p´ısmenem.
3.1
Z´ akladn´ı datov´ e typy
V programovac´ım jazyce Java existuje nˇekolik druh˚ u z´akladn´ıch datov´ ych typ˚ u: celoˇc´ıseln´e, logick´e, re´aln´e a znakov´e. Toto ˇclenˇen´ı odpov´ıd´ a ostatn´ım programovac´ım jazyk˚ um, nenalezneme zde tedy ˇz´adn´e ”pˇrekvapen´ı”. Z´akladn´ı datov´e typy nejsou v Javˇe povaˇzov´any za objekty, nen´ı proto s nimi moˇzno jako s objekty zach´azet. U kaˇzd´eho jednoduch´eho datov´eho typu je definov´ana jeho velikost v bajtech (tj. nen´ı urˇcov´ana operaˇcn´ım syst´emem), t´ım p´ adem se program st´ av´ a univerz´alnˇe pˇrenositeln´ y napˇr´ıˇc r˚ uzn´ ymi operaˇcn´ımi syst´emy.
3.1.1
Celoˇ c´ıseln´ e datov´ e typy
V Javˇe existuj´ı ˇctyˇri z´ akladn´ı celoˇc´ıseln´e datov´e typy. Vˇsechny jsou se znam´enky, neexistuje tedy u nich varianta bezznam´enka, tj. unsigned. Jejich pˇrehled je uveden v tab. 4.1. Datov´ y typ byte short int long
Velikost 8b 16b 32b 64b
Rozsah -128;127 -32768;32767 -2E09;2E09 -9E18;9E18
Tabulka 3.1: Pˇrehled celoˇc´ıseln´ych datov´ych typ˚ u v Javˇe. Chceme -li zapisovat hodnoty promˇenn´ ych a konstant, m˚ uˇzeme tak uˇcinit tˇremi zp˚ usoby: • V des´ıtkov´e soustavˇe (znaky 0-9): 9234 • V osmiˇckov´e soustavˇe (znaky 0-7): 0156
20
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Escape sekvence \n \r \t \\ \’ \"
UNICODE \u000A \u000D \u0009 \u005C \u002C \u0022
V´ yznam Nov´ a ˇr´ adka N´ avrat na zaˇc´ atek ˇr´ adku Tabul´ ator Zpˇetn´e lom´ıtko Apostrof Uvozovky
Tabulka 3.2: Pˇrehled escape sekvenc´ı a UNICODE k´ od˚ u nˇekter´ych d˚ uleˇzit´ych znak˚ u. • V ˇsestn´ actkov´e soustavˇe (znaky 0-9, a-f): Zaˇc´ın´ a znaky 0x a pokraˇcuje povolen´ ymi znaky, 0x26AF. Nutno vz´ıt v u ´vahu fakt, ˇze konstanty jsou standardnˇe datov´eho typu int. Pˇr´ıkaz a=123456; pˇriˇrad´ı promˇenn´e a hodnotu int. Chceme -li pˇriˇradit t´eto promˇenn´e hodnotu typu long, mus´ıme uv´est za ˇc´ıselnou hodnotou symbol L. a=12345678910L; Pokud nev´ıme, jak´ y datov´ y typ pouˇz´ıt, a nem´ ame nˇejak´e speci´ aln´ı poˇzadavky, zpravidla pouˇz´ıv´ ame typ int.
3.1.2
Znakov´ y typ
Java disponuje datov´ ym typem char, kter´ y se pouˇz´ıv´ a pro pr´ aci se znaky. Vyuˇz´ıv´ a k´ odov´ an´ı a sady znak˚ u UNICODE, velikost je 16 bit˚ u. Podmnoˇzinou UNICODE je znakov´ a sada ASCII, obsahuje prvn´ıch 127 znak˚ u. Znakov´e konstanty se zapisuj´ı nˇekolika zp˚ usoby: • jedn´ım znakem uzavˇren´ ym do apostrof˚ u: ’A’ • prostˇrednictv´ım escape sekvenc´ı (speci´ aln´ı znaky pro skok na nov´ y ˇr´ adek, tabul´ ator, atd.): ’\n’ • posloupnost´ı znak˚ u \’uXXXX’, kde XXXX pˇredstavuje k´ od znaku v k´ odov´ an´ı UNICODE: ’\u000A’ ´ Struˇcn´ y pˇrehled d˚ uleˇzit´ ych znak˚ u a jejich UNICODE k´ od˚ u nalezneme v tabulce 3.2. Upln´ y pˇrehled znakov´e sady UNICODE lze nal´ezt na str´ ance http://unicode.org. Pouˇz´ıv´ an´ı escape sekvenc´ı a UNICODE k´ od˚ u se odliˇsuje. UNICODE znaky se mohou vyskytovat kdekoliv v programu, napˇr. jako souˇc´ ast identifik´ ator˚ u, escape sekvence mohou b´ yt pouze souˇc´ ast´ı znakov´ ych a ˇretˇezcov´ ych konstant (viz d´ ale). double ko’\u010D’ka;//koˇ cka double ko’\99’ka//kocka, nelze Typ char m´ a vlastnosti celoˇc´ıseln´eho datov´eho typu bez znam´enka, jeho hodnota odpov´ıd´ a k´ odu pˇr´ısluˇsn´eho znaku. Na jednotliv´e znaky se m˚ uˇzeme d´ıvat jako na cel´ a ˇc´ısla, lze na nˇe aplikovat stejn´e oper´ atory jako na datov´ y typ int.
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Datov´ y typ float double
Velikost 32b 64b
Rozsah -1.4E45;3.4E48 -4.9E-324,1.7E308;
Tabulka 3.3: Pˇrehled re´ aln´ych datov´ych typ˚ u.
3.1.3
ˇ ezcov´ Retˇ e konstanty
ˇ ezcov´e Pro tvorbu ˇretˇezcov´ ych konstant plat´ı stejn´e z´ akonitosti jako pro tvorbu znakov´ ych konstant. Retˇ konstanty mohou b´ yt na rozd´ıl od znakov´e konstanty tvoˇreny v´ıce neˇz jedn´ım znakem. Nejsou zapisov´any do apostrof˚ u, ale do uvozovek. System.out.println("Ahoj"); System.out.println("Prvn\u00ED program\n v jazyce Java"); Java, na rozd´ıl od C++, umoˇzn ˇ uje sˇc´ıtat ˇretˇezcov´e konstanty prostˇrednictv´ım oper´ atoru +. "prvni slovo"+"druhe slovo";
3.1.4
Logick´ y datov´ y typ
Logick´ y datov´ y typ boolean nab´ yv´ a dvou hodnot: pravda resp. nepravda, tj. true resp. false. Obˇe hodnoty lze vyj´ adˇrit prostˇrednictv´ım celoˇc´ıseln´ ych hodnot: 1 resp. 0. Uplatˇ nuje se zejm´ena pˇri konstrukci logick´ ych podm´ınek. boolean vysledek=false;
3.2
Re´ aln´ e datov´ e typy
Re´ aln´ a ˇc´ısla jsou pˇredstavov´ ana desetinn´ ymi ˇc´ısly. Java disponuje dvˇema datov´ ymi typy pro pr´ aci s re´ aln´ ymi ˇc´ısly: float a double, viz tab. 3.3. Vˇsimnˇeme si, ˇze horn´ı a doln´ı hranice interval˚ u jsou nesymetrick´e. Re´aln´e konstanty lze zapsat r˚ uzn´ ymi zp˚ usoby: • Z´apisem s pevnou ˇr´ adovou ˇc´ arkou. Jedn´ a se o stejn´ y zp˚ usob z´ apisu, jak´ ym zapisujeme ˇc´ısla na pap´ır. Jako oddˇelovaˇc pouˇz´ıv´ ame desetinnou teˇcku. 123.456 10.0 • Z´apisem v semilogaritmick´em tvaru. T´ımto zp˚ usobem bˇeˇznˇe zapisujeme ˇc´ısla ”pˇr´ıliˇs mal´ a” nebo ”pˇr´ıliˇs velk´a”: 0.1 ∗ 1010 nebo 0.1 ∗ 10−10 . 0.1e10 0.1e-10 Re´ aln´ a konstanta je standardnˇe datov´eho typu double. Chceme-li ji zmˇenit na float, mus´ıme za posledn´ı ˇc´ıslici um´ıstit znak F. a=0.1e10F;
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Maxim´ aln´ı a minim´ aln´ı hodnota. Maxim´ aln´ı a minim´ aln´ı hodnoty pro celoˇc´ıseln´e i re´ aln´e datov´e typy lze z´ıskat prostˇrednictv´ım konstant MIN_VALUE a MAX_VALUE. Pˇred konstantu um´ıst´ıme oznaˇcen´ı datov´eho typu v objektov´e variantˇe. Syntaxe vypad´ a takto: Integer.MAX_VALUE; Double.MIN_VALUE; Na z´ avˇer uved’me dvˇe speci´ aln´ı hodnoty, kter´e mohou vzniknout pˇri ”nevhodn´em” dˇelen´ı nˇejak´eho ˇc´ısla jin´ ym ˇc´ıslem. Dˇel´ıme -li kladn´e resp. z´ aporn´e ˇc´ıslo 0, v´ ysledkem operace je nekoneˇcno, tj. hodnota POSITIVE_INFINITY resp. NEGATIVE_INFINITY. Dˇel´ıme -li 0 nulou, tj 0/0, v´ ysledkem operace je hodnota NaN, tj. not a number.
3.3
Deklarace promˇ enn´ ych
Deklarace promˇenn´e pˇredstavuje krok, pˇri kter´em vytvoˇr´ıme promˇennou zvolen´eho jm´ena nˇekter´eho z v´ yˇse uveden´ ych datov´ ych typ˚ u a pˇriˇrad´ıme ji (tj. inicializujeme ji) na nˇejakou poˇc´ ateˇcn´ı hodnotu. Tento typ inicializace oznaˇcujeme jako explicitn´ı. Jestliˇze neuvedeme ˇz´ adnou inicializaˇcn´ı hodnotu, je promˇenn´ a inicializov´ ana implicitnˇe, tj. na v´ ychoz´ı hodnotu pro zvolen´ y datov´ y typ. Pˇripomeˇ nme, ˇze implicitn´ı inicializace probˇehne pouze v pˇr´ıpadˇe, ˇze promˇenn´a pˇredstavuje datovou poloˇzku tˇr´ıdy. Pokud by se jednalo o promˇennou, kter´ a nepˇredstavuje datovou poloˇzku tˇr´ıdy, a nedoˇslo by k jej´ı explicitn´ı inicializaci pˇred prvn´ım pouˇzit´ım, upozorn´ı n´ as Java na tento nedostatek. Odstraˇ nuje tak jednou z velk´ ych nev´ yhod nˇekter´ ych jazyk˚ u, tj. moˇznost pr´ ace s neinicializovan´ ymi promˇenn´ ymi. int a; double b, c, d; Uved’me struˇcnˇe nˇekter´e z´ asady ˇci vlastnosti souvisej´ıc´ı s deklaracemi promˇenn´ ych: • V Javˇe neexistuj´ı jako v C++ glob´ aln´ı promˇenn´e. Nen´ı moˇzn´e vytvoˇrit promˇennou, kter´ a by byla dostupn´ a v cel´em programu. Deklarace totiˇz nesm´ı b´ yt um´ıstˇena vnˇe tˇr´ıdy, jak je to v C++ bˇeˇzn´e napˇr. ve spojitosti s kl´ıˇcov´ ym slovem extern. • V Javˇe nerozliˇsujeme pojmy definice promˇenn´e a deklarace promˇenn´e. nelze totiˇz vytvoˇrit a pouˇz´ıt promˇennou bez jej´ı implicitn´ı ˇci explicitn´ı inicializace. • Je vhodn´e dodrˇzovat z´asadu: deklarace promˇenn´ ych by z d˚ uvodu pˇrehlednosti mˇely b´ yt um´ıstˇeny na zaˇc´ atku bloku. Pr´ ace s konstantami. Java pouˇz´ıv´ a jin´ y pˇr´ıstup pˇri deklaraci konstant. Konstanty jsou deklarov´any s kl´ıˇcov´ ym slovem final. Hodnotu konstanty jiˇz nelze d´ ale mˇenit. final int CISLO=10; Pˇr´ıkaz CISLO=15; //Chyba
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E zp˚ usob´ı vyvol´an´ı chyby, program nebude moˇzno pˇreloˇzit. Plat´ı z´ asada, ˇze jm´ena konstant by mˇela b´ yt tvoˇrena pouze velk´ ymi p´ısmeny. Pokud chceme pouˇz´ıt konstantu vnˇe tˇr´ıdy, ve kter´e ”vznikly”, je nutno jejich deklaraci prov´est vnˇe vˇsech metod, nastavit ji jako veˇrejnou, tj. za pouˇzit´ı kl´ıˇcov´eho slova public. Jelikoˇz se bude jednat o promˇennou tˇr´ıdy, nezapomeˇ nme, ˇze mus´ı b´ yt spoleˇcn´ a pro vˇsechny instance, je nutno ji deklarovat jako statickou za pouˇzit´ı kl´ıˇcov´eho slova static. public class Neco { public static final int CISLO=10; //staticka promenna neco }
3.4
Pˇ riˇ razov´ an´ı a pˇ retypov´ an´ı
Pˇriˇrazovac´ı pˇr´ıkaz je pouˇz´ıv´ an pˇri pr´ aci s promˇenn´ ymi i konstantami. Oper´ atorem pˇriˇrazen´ı je znak =, oper´ator == pˇredstavuje relaˇcn´ı oper´ ator ”je rovno”. Pˇriˇrazovac´ı pˇr´ıkaz umoˇzn ˇuje pˇriˇradit hodnotu nˇejak´eho v´ yrazu jin´e promˇenn´e nach´ azej´ıc´ı se vlevo od oper´ atoru =. V´ yraz, kter´ y do promˇenn´e pˇriˇrazujeme, mus´ı m´ıt nˇejakou hodnotu. a=10.0; b=c+15*f; znak=’A’; Pˇriˇrazovac´ı pˇr´ıkaz m˚ uˇze b´ yt pouˇz´ıv´ an i pˇri tvorbˇe logick´ ych podm´ınek. Zaˇc´ ateˇcn´ıka by nemˇela zm´ ast n´asleduj´ıc´ı konstrukce if (a==(b=10)); pˇredstavuj´ıc´ı dotaz, zda hodnota promˇenn´e a je rovna hodnotˇe promˇenn´e b, kter´ a je inicializov´ ana na 10. Pˇ retypov´ an´ı. Pˇri pˇriˇrazovac´ıch operac´ıch doch´ az´ı ˇcasto ke konverz´ım mezi r˚ uzn´ ymi datov´ ymi typy. Tyto operace naz´ yv´ ame pˇretypov´ an´ım. V´ ysledkem pˇriˇrazen´ı je zmˇena datov´eho typu promˇenn´e. Existuj´ı dva typy pˇretypov´an´ı: • Implicitn´ı konverze Vznik´a pˇri pˇretypov´ an´ı promˇenn´e s niˇzˇs´ım rozsahem na promˇennou s vyˇsˇs´ım rozsahem. Prob´ıh´a automaticky bez nutnosti z´ apisu jak´ehokoliv programov´eho k´ odu. Nedoch´ az´ı pˇri n´ı ke ztr´ atˇe informac´ı. Pro v´ yˇse uveden´e datov´e typy b´ yv´ a prov´ adˇena v n´ asleduj´ıc´ım poˇrad´ı: byte->short->int->long->float>double.
float a=50; double b=30; b=a;//implicitni konverze • Explicitn´ı konverze Vznik´ a pˇri pˇretypov´ an´ı promˇenn´e s vyˇsˇs´ım rozsahem na promˇennou s niˇzˇs´ım rozsahem. Konverze neprobˇehne automaticky (m˚ uˇze pˇri n´ı doj´ıt k sn´ıˇzen´ı pˇresnosti dat), je tedy nutno vynutit ji uveden´ım v´ ysledn´eho datov´eho typu. Pˇri explicitn´ı konverzi doch´ az´ı zpravidla ke ztr´ atˇe informac´ı. B´ yv´ a prov´adˇena v n´ asleduj´ıc´ım poˇrad´ı: double->float->long->int->short->byte.
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E a=b;//ztrata presnosti, nelze provest a=(float)b;//explicitni konverze Pˇretypov´an´ı lze pouˇz´ıvat u OOP tak´e pˇri pr´ aci s rodiˇcovskou a odvozenou tˇr´ıdou. Objekt rodiˇcovsk´e tˇr´ıdy oznaˇc´ıme rodiˇc, objekt odvozen´e tˇr´ıdy potomek. Potomek b´ yv´ a zamˇeˇren u ´ˇzeji neˇz rodiˇc. Existuj´ı dvˇe moˇznosti pˇretypov´ an´ı: • Pˇretypov´an´ı z potomka na rodiˇce: implicitn´ı konverze • Pˇretypov´an´ı z rodiˇce na potomka: explicitn´ı konverze Podrobnˇeji se s nimi sezn´ am´ıme v kapitole vˇenovan´e objektovˇe orientovan´emu programov´ an´ı. Sm´ıˇ sen´ e konverze. Pod´ıvejme se na situace, kdy do aritmetick´ ych operac´ı vstupuj´ı operandy sm´ıˇsen´eho typu, hovoˇr´ıme pak o tzv. sm´ıˇsen´ ych v´ yrazech. Plat´ı n´ asleduj´ıc´ı z´ akonitosti: 1. Pokud je jeden z operand˚ u typu double, bude v´ ysledkem operace datov´ y typ double 2. Pokud je jeden z operand˚ u typu float, bude v´ ysledkem operace datov´ y typ float 3. Pokud je jeden z operand˚ u typu long, bude v´ ysledkem operace datov´ y typ long Jejich c´ılem je realizace aritmetick´ ych operac´ı tak, aby pˇri nich doˇslo k co nejmenˇs´ı ztr´ atˇe pˇresnosti. Pozor mus´ıme d´ at u v´ yraz˚ u obsahuj´ıc´ıch zlomky, pokud ˇcitatel i jmenovatel pˇredstavuj´ı celoˇc´ıseln´e hodnoty. V´ ysledek operace bude opˇet datov´eho typu int. int a=5;//int int b=10;//int int c=a/b;//vysledek=0 V´ yˇse uveden´ y z´ apis je z form´ aln´ıho hlediska ˇspatn´ ym, nemˇel by b´ yt nikdy pouˇzit. Spr´ avn´ y je n´ asleduj´ıc´ı z´ apis, pˇri kter´em vznikne sm´ıˇsen´ y v´ yraz: int a=5.0;//double int b=10;//int int c=a/b;//vysledek=0.5; Objektov´ e datov´ e typy a pˇ riˇ razov´ an´ı. Uved’me pro u ´plnost, ˇze i kdyˇz vytvoˇr´ıme datov´ y typ jako objektov´ y, tak nem´ a rysy skuteˇcn´eho objektu, napˇr. operace pˇriˇrazen´ı je prov´ adˇena nikoliv odkazem, jak bychom oˇcek´ avali, ale stejnˇe jako u primitivn´ıho datov´eho typu hodnotou. Java tedy nen´ı stroprocentnˇe objektov´ y jazyk, jak je patrn´e. Konverze z´ akladn´ıch datov´ ych typ˚ u, ˇ retˇ ezc˚ u a znak˚ u. Vz´ ajemn´e konverze primitivn´ıch datov´ ych typ˚ u a ˇretˇezc˚ u jsou pouˇz´ıv´ any velmi ˇcasto. Chceme -li konvertovat nˇekter´ y ze z´ akladn´ıch datov´ ych typ˚ u na datov´ y typ String, pouˇzijeme statickou metodu tˇr´ıdy String s n´ azvem valueOf(). int a=10; boolean b=true; double c=15.0; String retezec=String.valueOf(a); String retezec=String.valueOf(b); String retezec=String.valueOf(c);
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Konverzi z´akladn´ıho datov´eho typu na ˇretˇezec lze prov´est i ”fintou” se sˇc´ıt´ an´ım pr´ azdn´eho ˇretˇezce a promˇenn´e: String retezec=""+a; Opaˇcn´ y postup, pˇri kter´em konvertujeme ˇretˇezec na nˇekter´ y ze z´ akladn´ıch datov´ ych typ˚ u, lze prov´est dvˇema zp˚ usoby: • Starˇs´ı pˇr´ıstup, kter´ y je ponˇekud tˇeˇzkop´ adn´ y. Je dan´ı za ne 100% “objektovost” jazyka Java. V prvn´ım kroku provedeme konverzi ˇretˇezce na objekt pˇr´ısluˇsn´e tˇr´ıdy za pouˇzit´ı metody valueof(). Tento objekt je nutno v n´ asleduj´ıc´ım kroku pˇrev´est na primitivn´ı datov´ y typ prostˇrednictv´ım nˇekter´e z trojice metod: intValue(), doubleValue(), booleanValue(); String retezec=”1234”; int a=String.valueOf(retezec).intValue(); double b=String.valueOf(retezec).doubleValue(); bool c=String.valueOf(retezec).booleanValue(); • Novˇejˇs´ı pˇr´ıstup vych´ azej´ıc´ı z JDK prostˇrednictv´ım metod parseLong(), parseDouble(), parseFloat(). String retezec="1234"; String retezec2="true"; int a=(int)Long.parseLong(retezec); Chceme -li pˇretypovat znakovou konstantu na nˇekter´ y z primitivn´ıch datov´ ych typ˚ u, pouˇzijeme metodu digit(). char znak=’A’; int cislo=Character.digit(znak); V´ yˇse uveden´e konverzn´ı postupy pouˇzijeme pˇri pr´ aci se standardn´ım vstupem a v´ ystupem.
3.5
Oper´ atory v Javˇ e
Kromˇe oper´ atoru pˇriˇrazen´ı, se kter´ ym jsme se jiˇz sezn´ amili, je v Javˇe pouˇz´ıv´ ana ˇrada dalˇs´ıch typ˚ u oper´ator˚ u. Aritmetick´ e oper´ atory. Aritmetick´e oper´ atory jejich struˇcn´ y popis jsou zobrazeny v tabulce 3.4. Slouˇz´ı k realizaci z´ akladn´ıch aritmetick´ ych operac´ıch. Pˇri jejich vyhodnocov´ an´ı se postupuje ve smˇeru zleva do prava dle priority: nejprve operace n´ asoben´ı/dˇelen´ı/celoˇc´ıseln´e dˇelen´ı, pot´e se vyhodnot´ı zb´ yvaj´ıc´ı operace. Oper´ ator + * / %
Popis Sˇc´ıt´ an´ı Odeˇc´ıt´ an´ı N´ asoben´ı Dˇelen´ı Zbytek po celoˇc´ıseln´em dˇelen´ı.
Tabulka 3.4: Pˇrehled aritmetick´ych oper´ ator˚ u.
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Oper´ ator a+=5 a-=5 a*=5 a/=5
´ Upln´ y z´ apis a=a+5 a=a-5 a=a*5 a=a/5
Tabulka 3.5: Pˇrehled oper´ ator˚ u inkrementace a dekrementace. Chceme -li zmˇenu priority vyhodnocov´ an´ı prov´est umˇele, m˚ uˇzeme tak pouˇz´ıt z´ avorky. Poˇcet prav´ ych a lev´ ych z´ avorek by mˇel b´ yt stejn´ y. int a=3+3*3;//a=12 int a=(3+3)*3;//18 Oper´ atory pˇ riˇ razen´ı. Oper´ atory pˇriˇrazen´ı pˇredstavuj´ı kombinaci pˇriˇrazen´ı a aritmetick´ ych oper´ator˚ u. Tyto oper´atory umoˇzn ˇuj´ı zkr´ acen´ y z´ apis bˇeˇzn´ ych aritmetick´ ych operac´ı. Oper´ atory inkrementace a dekrementace. Oper´ atory inkrementace a dekrementace umoˇzn ˇuj´ı zvyˇsov´ an´ı ˇci sniˇzov´ an´ı hodnoty promˇenn´e o 1. Jedn´ a se o “zdvojen´e” oper´ atory ++ resp. −−. Nˇekteˇr´ı zl´ı jazykov´e tvrd´ı, ˇze Java=C+ + −−, tj. ˇze Java je to sam´e to sam´e C++ :-). Existuj´ı dva typy inkrementace resp. dekrementace: • pˇredch´ azej´ıc´ı inkrementace/dekrementace. Pˇri n´ı jsou oper´ atory inkrementace/dekrementace um´ıstˇeny pˇred promˇennou. V tomto pˇr´ıpadˇe se nejprve provede pˇriˇrazovac´ı pˇr´ıkaz a aˇz n´ aslednˇe inkrementace/dekrementace promˇenn´ ych. int a=5, b=5; int c=++a;//a=6, c=5; int d=--b;//b=4, d=5; • n´ asledn´ a inkrementace/dekrementace. Pˇri n´ı jsou oper´ atory inkrementace/dekrementace um´ıstˇeny za promˇennou. V tomto pˇr´ıpadˇe se nejprve provede inkrementace/dekrementace a aˇz n´ aslednˇe pˇriˇrazovac´ı pˇr´ıkaz. int a=5, b=5; int c=a++;//a=6, c=6; int d=b--;//b=4, d=4; Relaˇ cn´ı oper´ atory. Relaˇcn´ı oper´ atory se pouˇz´ıvaj´ı pˇri konstruov´ an´ı logick´ ych podm´ınek. Pˇrehled relaˇcn´ıch oper´ ator˚ u je uveden v tab. 3.5.
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Oper´ ator == != && || ! < > <= >=
Popis Rovn´ a se Nerovn´ a se Logick´ y souˇcin Logick´ y souˇcet Negace Menˇs´ı Vˇetˇs´ı Menˇs´ı nebo rovno Vˇetˇs´ı nebo rovno
Tabulka 3.6: Pˇrehled relaˇcn´ıch oper´ ator˚ u.
3.6
Matematick´ e metody
Java disponuje jak z´ akladn´ımi, tak pokroˇcil´ ymi matematick´ ymi funkcemi. Ty jsou um´ıstˇeny ve tˇr´ıdˇe Math, kter´ a se nach´ az´ı v bal´ıku java.lang. Pˇredstavuj´ı jednotliv´e metody tˇr´ıdy Math, proto k nim m˚ uˇzeme pˇristupovat za pouˇzit´ı syntaxe Math.Metoda(parametr). Metoda m˚ uˇze b´ yt vol´ ana s form´ aln´ımi parametry, kter´e se zapisuj´ı do z´ avorek. V´ ysledkem v´ ypoˇctu je vˇzdy pouze jedna hodnota. double Ro=180/Math.PI; double vysledek=Math.sin(45/Ro); Pro u ´plnost uved’me, ˇze stejnˇe jako v ostatn´ıch jazyc´ıch, jsou vstupn´ı hodnoty trigonometrick´ ych funkc´ı uv´adˇeny v radi´ anech. Chceme -li v naˇsem programu vyuˇz´ıvat matematick´e metody a nechceme -li je kvalifikovat n´ azvem bal´ıˇcku, mus´ıme importovat bal´ıˇcek Math. import java.math.*; Nˇekter´e metody jsou pˇret´ıˇzen´e, existuje v´ıce metod se stejn´ ym n´ azvem, jejich vstupn´ı parametry jsou vˇsak r˚ uzn´e: float, double, int, long. Pokud nen´ı vstupn´ı hodnota poˇzadovan´eho datov´eho typu, je provedena jej´ı konverze (vynucen´ a konverze), pokud to je moˇzn´e. Vˇetˇsina z matematick´ ych metod poskytuje v´ ysledek typu double. Pˇrehled nejˇcastˇeji pouˇz´ıvan´ ych metod nalezneme v tabulce 3.7.
3.7
Pr´ ace se standardn´ım form´ atovan´ ym vstupem a v´ ystupem
Pˇri bˇehu programu mus´ı existovat moˇznost zad´ av´ an´ı vstupn´ıch dat (vstupn´ı parametry pro v´ ypoˇcet) i moˇznost pr´ ace s v´ ystupn´ımi daty (v´ ysledky v´ ypoˇct˚ u). Hovoˇr´ıme o termin´ alov´em vstupu a v´ ystupu. Upozornˇeme, ˇze standardn´ı form´ atovan´ y vstup a v´ ystup nejsou v Javˇe na rozd´ıl od jazyka C++ urˇceny pro v´ aˇznou pr´aci, ale pouze pro v´ yukov´e u ´ˇcely. Java totiˇz disponuje grafick´ ym rozhran´ım umoˇzn ˇuj´ıc´ım prov´ adˇet vstup/v´ ystup u ´daj˚ u s vyuˇzit´ım vizu´ aln´ıch komponent, napˇr. textfield˚ u ˇci editbox˚ u, seznam˚ u. Pr´ ace s termin´ alov´ ym vstupem je v Javˇe ponˇekud komplikovanˇejˇs´ı neˇz v jazyce C++. N´ astroje pro pr´ aci se standardn´ım vstupem a v´ ystupem se nach´ azej´ı v bal´ıku java.io. Chceme -li pracovat se standardn´ım vstupem a v´ ystupem, pouˇzijeme import java.io.*; Pro pr´ aci se standardn´ım form´ atovan´ ym vstupem v Javˇe existuj´ı objekty System.in a System.out. Objekt System.in realizuje standardn´ı vstup, nejˇcastˇeji ˇcten´ım hodnot z kl´ avesnice. System.out je objekt, kter´ y se pouˇz´ıv´ a pro zobrazov´ an´ı v´ ystupn´ıch u ´daj˚ u na monitoru.
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Funkce
Mat. z´ apis
Math.abs(x)
|x|
Math.acos(x) Math.asin(x) Math.atan(x) Math.atan2(y,x) Math.ceil(x) Math.cos(x) Math.exp(x) Math.floor(x) Math.log(x) Math.max(x,y) Math.min(x,y) Math.random(x) Math.pow(x,y) Math.round(x,y) Math.sin(x) Math.sqrt(x) Math.tan(x)
arccos(x) arcsin(x) arctg(x) arctg(y/x) int(x + 0.5) cos(x) ex int(x-0.5) ln(x) max(x,y) min(x,y) xy int(x+0.5) sin(x) √ x tg(x)
Vstupn´ı hodnoty int, long, float, double double double double double double double double double double int, float, double int, float, double double double, float double double double
V´ ystupn´ı hodnoty int, long, float, double double double double double double double double double double int, float, double int, float, double double double double, float double double double
Tabulka 3.7: Pˇrehled vybran´ych matematick´ych funkc´ı.
3.7.1
Form´ atovan´ y v´ ystup
Pro form´ atovan´ y v´ ystup je pouˇz´ıv´ an objekt System.out. S pouˇzit´ım metody print() m˚ uˇzeme prov´est vytisknut´ı ˇretˇezce na aktu´ aln´ı pozici v ˇr´ adku. Pokud se na v´ ystup dostane hodnota jin´eho datov´eho typu neˇz ˇretˇezec, je provedena vynucen´ a konverze na ˇretˇezec. int a=10; int b=20; System.out.print(a); System.out.print(b); System.out.print("Ahoj"); Na v´ ystupu se objev´ı: 1020Ahoj. Na rozd´ıl od jazyka C++ nen´ı moˇzno hodnoty na v´ ystupu nijak form´atovat, tj. napˇr. stanovit poˇcet desetinn´ ych m´ıst. Chceme -li zˇretˇezit hodnoty na v´ ystupu, tj. vytisknout v jednom kroku v´ıce u ´daj˚ u, pouˇzijeme oper´ ator +. M˚ uˇzeme vz´ ajemnˇe sˇc´ıtat ”hruˇsky s jablky”, tj. jak ˇretˇezce, tak i promˇenn´e primitivn´ıch datov´ ych typ˚ u. Pouˇzijeme System.out.print ("a="+a+" b="+b+" Ahoj"); obdrˇz´ıme na v´ ystupu:a=10 b=20 Ahoj. V ˇretˇezci se mohou vyskytnout i escape sekvence, uved’me dvˇe nejˇcastˇeji pouˇz´ıvan´e: • znak ’\t’ (znakov´ a konstanta) resp. ”\t” (ˇc´ ast ˇretˇezce): tabul´ ator. • znak ’\n’ (znakov´ a konstanta) resp. ”\n” (ˇc´ ast ˇretˇezce): pˇrechod na novou ˇr´ adku. Pˇr´ıkazy
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E System.out.print ("a="+a+"\n"+"b="+b+"\n Ahoj"); System.out.print ("jak"+"\t"+"se"+"\tmate"); vytisknou na obrazovku a=10 b=20 Ahoj jak
se
mate
Stejn´eho efektu dos´ ahneme za pouˇzit´ı metody println(). System.out.println("a="+a); System.out.println("b"+b); System.out.println("jak"+"\t"+"se"+"\tmate");
3.7.2
Standardn´ı form´ atovan´ y vstup
Pr´ ace s form´atovan´ ym vstupem v Javˇe je ponˇekud sloˇzitˇejˇs´ı neˇz v jazyce C++. Je pouˇz´ıv´ an objekt System.in. Pˇri zad´ av´ an´ı znak˚ u z kl´ avesnice jsou jednotliv´e znaky interpretov´ any jako bajty zakonˇcen´e ukonˇcovac´ım znakem ’\n’. Je vhodn´e je proto naˇc´ıst do pole bajt˚ u. V n´ asleduj´ıc´ım pˇr´ıkladu si uk´ aˇzeme naˇcten´ı dat z form´ atovan´eho vstupu a jejich konverze na typ int. byte [] pole=new byte [30]; System.in.read(pole); Bajty n´ aslednˇe pˇrevedeme na ˇretˇezec typu String String retezec=new String(pole); a oˇr´ızneme ukonˇcovac´ı znaky retezec=retezec.trim(); N´ aslednˇe provedeme konverzi String na typ int. Nezapomeˇ nme na explicitn´ı pˇretypov´ an´ı. int cislo=(int)Long.parseLong(retezec); Obdobn´ ym zp˚ usobem bychom postupovali i pˇri konverzi na jin´e datov´e typy: double cislo=Double.parseDouble(retezec); Tento k´od je vhodn´e obalit do konstrukce try/catch pro odchycen´ı pˇr´ıpadn´e v´ yjimky vznikl´e napˇr, t´ım, ˇze uˇzivatel na vstupu zad´ a textov´ y ˇretˇezec obsahuj´ıc´ı jeden nebo v´ıce znak˚ u, kter´e nejsou ˇc´ıslicemi. S t´ımto pˇr´ıstupem se setk´ ame aˇz v ˇc´ asti vˇenovan´e odchycov´ an´ı v´ yjimek.
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E
3.8
Pˇ r´ıkazy v Javˇ e
Pˇr´ıkazy pˇredstavuj´ı z´ akladn´ı stavebn´ı jednotky program˚ u. S jejich vyuˇzit´ım pˇrepisujeme algoritmy do prostˇred´ı pˇr´ısluˇsn´eho form´ aln´ıho jazyka (tj. programovac´ıho jazyka). Pˇr´ıkazy jsou zpravidla prov´ adˇeny v poˇrad´ı, v jak´em byly program´ atorem zaps´ any. Pˇr´ıkazy v Javˇe jsou velmi podobn´e pˇr´ıkaz˚ um v jazyce C++. V Javˇe rozezn´ av´ ame dva typy pˇr´ıkaz˚ u: jednoduch´ y pˇr´ıkaz a sloˇzen´ y pˇr´ıkaz. Jednoduch´y pˇr´ıkaz je ukonˇcen stˇredn´ıkem System.out.println ("Ahoj"); //jednoduch´ y pˇ r´ ıkaz Plat´ı z´ asada, ˇze na kaˇzd´em ˇr´ adku by mˇel b´ yt um´ıstˇen pouze jeden pˇr´ıkaz, program by se v opaˇcn´em pˇr´ıpadˇe stal nepˇrehledn´ ym. Sloˇzen´y pˇr´ıkaz je uzavˇren do sloˇzen´ ych z´ avorek a vytv´ aˇr´ı blok. Pˇredstavuje skupinu pˇr´ıkaz˚ u, kter´ a se z hlediska syntaxe Javy chov´ a jako jedin´ y pˇr´ıkaz. Za blokem nep´ıˇseme stˇredn´ık. if (a
3.9
Pole
Pole pˇredstavuje skupinu promˇenn´ ych stejn´eho datov´eho typu, se kter´ ymi m˚ uˇze zach´ azet jako s celkem. Pole je jeden z dvou neprimitivn´ıch datov´ ych typ˚ u, druh´ y je objekt. Jednotliv´e promˇenn´e naz´ yv´ ame prvky pole. Lze k nim pˇristupovat za pouˇzit´ı jm´ena pole a indexu (ten je uv´ adˇen v hranat´ ych z´ avork´ ach).
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E Index pˇredstavuje poˇradov´e ˇc´ıslo prvku pole od jeho poˇc´ atku. Oznaˇc´ıme -li celkov´ y poˇcet prvk˚ u pole n, u ´vodn´ı prvek pole m´ a index 0, posledn´ı prvek pole m´ a index n-1. Index mus´ı vˇzdy pˇredstavovat kladn´e cel´e ˇc´ıslo. Pr´ ace s polem je v Javˇe bezpeˇcnˇejˇs´ı neˇz v C++, kde pole pˇredstavuj´ı pouze bloky pamˇeti. V Javˇe je automaticky prov´adˇena kontrola pˇrekroˇcen´ı indexu pole, k ˇradˇe chyb tˇeˇzko odhaliteln´ ych v C/C++ zde nedoch´az´ı. Dynamicky vytvoˇren´e pole nemus´ıme ruˇsit manu´ alnˇe, pokud na nˇej neexistuje platn´ y odkaz, je zruˇseno prostˇrednictv´ım garbage collectoru. Pr´ ace s polem. S polem se v Javˇe pracuje prostˇrednictv´ım odkazu, tj. podobnˇe jako s objekty. Nejprve je nutno deklarovat odkaz na pole, n´ aslednˇe se vytvoˇr´ı pole samotn´e. Odkaz na obecn´e pole lze vytvoˇrit n´ asleduj´ıc´ı konstrukc´ı: datovy_typ [] identifikator. Odkaz na pole typu double double [] pole; V deklaraci se neuv´ ad´ı poˇcet prvk˚ u pole. Pˇri deklaraci nedoch´ az´ı k pˇridˇelen´ı pamˇeti pro pole, jak´ akoliv operace s takov´ ym polem skonˇc´ı vyvol´ an´ım v´ yjimky. Druh´ y krok pˇredstavuje vytvoˇren´ı vlastn´ıho pole znamenaj´ıc´ı pˇridˇelen´ı potˇrebn´e pamˇeti a nastaven´ı odkazu tak, aby ukazoval na vytvoˇren´e pole. Budeme vytv´ aˇret pole o 10 prvc´ıch pole=new double[10]; Poˇcet prvk˚ u pole je pˇri jeho vytv´ aˇren´ı uv´ adˇen v hranat´ ych z´ avork´ ach. Oba kroky lze spojit do jednoho double [] pole=new double[10]; Po vytvoˇren´ı kompil´ ator zaruˇc´ı, ˇze prvky pole budou inicializov´ any na hodotu 0, u pol´ı typu boolean na hodnotu false, u pol´ı odkaz˚ u (tj. referenc´ı) na hodnotu null. Z v´ yˇse uveden´eho postupu vid´ıme, ˇze s polem se pracuje podobnˇe jako s objektem. D´ elka pole. D˚ uleˇzitou vlastnost´ı pole je jeho d´elka, tj. poˇcet prvk˚ u. Lze ji urˇcit prostˇrednictv´ım promˇenn´e length. V´ ysledkem je kladn´ a celoˇc´ıseln´ a hodnota. pole.length; Tuto hodnotu je vhodn´e pouˇz´ıt pˇri proch´ azen´ı prvk˚ u pole pomoc´ı cyklu jako horn´ı mez. Inicializovan´ e pole. Existuje moˇznost vytvoˇrit pole inicializovan´e pˇredem dan´ ymi hodnotami, v takov´em pˇr´ıpadˇe se nepouˇz´ıv´ a konstrukce s new. double [] pole={2.0, 4.4,17.85}; Poˇcet prvk˚ u nemus´ıme uv´ adˇet, kompil´ ator si je spoˇc´ıt´ a “s´ am”. S takto vytvoˇren´ ym polem se pracuje stejnˇe jako s jak´ ymkoliv jin´ ym vytvoˇren´ ym polem. Pˇr´ıstup k jednotliv´ ym prvk˚ um pole lze prov´ adˇet pˇres index. N´ asleduj´ıc´ı pˇr´ıkaz pˇriˇrad´ı promˇenn´e cislo hodnotu druh´eho prvku pole. double cislo=pole[1];
´ TYPY A PROMENN ˇ ´ V JAVE ˇ KAPITOLA 3. DATOVE E V´ıcerozmˇ ern´ e pole. Pˇri sloˇzitˇejˇs´ıch matematick´ ych v´ ypoˇctech pouˇz´ıv´ ame ˇcasto dvojrozmˇern´ a ˇci trojrozmˇern´ a pole, typick´ ym pˇr´ıkladem jsou matice. Pr´ ace s v´ıcerozmˇern´ ym polem je analogi´ı pr´ ace s jednorozmˇern´ ym polem, pro pˇr´ıstup ke konkr´etn´ımu prvku pouˇzijeme dvojici index˚ u. double [][] pole2d; pole2d=new double[10][10]; Poˇcet ˇr´adk˚ u pole lze z´ıskat jako pole2d.lenght; poˇcet sloupc˚ u pole jako pole2d[i].length; kde i pˇredstavuje index libovoln´eho ˇr´ adku pole. V´ıcerozmˇ ern´ e inicializovan´ e pole. Lze ho vytvoˇrit stejn´ ym zp˚ usobem jako jednorozmˇern´e inicializovan´e pole, tj. bez pouˇzit´ı konstrukce new. N´ asleduj´ıc´ı konstrukce vytvoˇr´ı dvourozmˇern´e pole o tˇrech ˇr´ adc´ıch a dvou sloupc´ıch. double [][] pole2d={{2.0, 4.4},{17.85, 0.3}, {10.9, 6.4}}; S poli zpravidla pracujeme za pouˇzit´ı cykl˚ u (viz d´ ale), jednotliv´e prvky lze efektivnˇeji proch´ azet.
3.9.1
Kop´ırov´ an´ı pol´ı
Pˇri kop´ırov´an´ı dvou pol´ı nelze pouˇz´ıt pˇriˇrazovac´ı pˇr´ıkaz, prov´ adˇeli bychom pouze kop´ırov´ an´ı odkaz˚ u, nikoliv kop´ırov´ an´ı skuteˇcn´eho obsahu pol´ı. N´ asleduj´ıc´ı konstrukce je chybn´ a. int [] pole1={1,2,3}; int [] pole2=new int [3]; pole2=pole1;//zkopirovani odkazu, nikoliv pole! Doˇslo ke zkop´ırov´ an´ı odkazu na pole1 do pole2. Odkazy pole1 a pole2 ukazuj´ı fyzicky na stejn´e pole. Chceme -li prov´ adˇet kop´ırov´ an´ı obsahu pol´ı, pˇrep´ıˇseme konstrukci do tvaru int [] pole1={1,2,3}; int [] pole2=new int [3]; for (int i=0;i<pole1.length;i++) pole2[i]=pole1[i]; V tomto pˇr´ıpadˇe prov´ ad´ıme kop´ırov´ an´ı prvek po prvku za pouˇzit´ı cyklu. Existuje i pˇr´ıkaz arraycopy, kter´ y prov´ ad´ı stejnou ˇcinnost pohodlnˇeji. int [] pole1={1,2,3}; int [] pole2=new int [3]; System.arraycopy(pole1,0,pole2,0,pole.length); M´ a celkem 5 parametr˚ u. Prvn´ı pˇredstavuje pole, jehoˇz obsah chceme kop´ırovat, druh´ y pozici, od kter´e kop´ırujeme, tˇret´ı pole, do kter´eho kop´ırujeme, ˇctvrt´ y pozici, od kter´e chceme zkop´ırovan´e prvky ukl´ adat, p´at´ y celkov´ y poˇcet zkop´ırovan´ ych prvk˚ u.
Kapitola 4
Vˇ etven´ı programu a opakov´ an´ı Pˇr´ıkazy pro vˇetven´ı b´ yvaj´ı ˇcasto oznaˇcov´ any jako tzv. ˇr´ıd´ıc´ı struktury. Umoˇzn ˇuj´ı prov´adˇet vˇetven´ı programu a ovlivnit, kter´e pˇr´ıkazy budou provedeny v z´avislosti na hodnot´ach logick´ ych v´ yraz˚ u (tj. podm´ınek). Pˇr´ıkazy pro opakov´an´ı naz´ yv´ ame iteraˇcn´ımi pˇr´ıkazy, umoˇzn ˇ uj´ı opakovanˇe prov´adˇet jeden nebo v´ıce pˇr´ıkaz˚ u. Patˇr´ı k nejˇcastˇeji pouˇz´ıvan´ ym konstrukc´ım.
4.1
Pˇ rehled pˇ r´ıkaz˚ u pro vˇ etven´ı programu
4.1.1
Konstrukce if-else
Tento pˇr´ıkaz nalezneme prakticky ve vˇsech programovac´ıch jazyc´ıch. V Javˇe se vyskytuje ve dvou variant´ach, a to jako podm´ınka u ´ pln´ a nebo podm´ınka ne´ upln´a. Ne´ upln´ a podm´ınka. Ne´ uplnou podm´ınku lze zapsat jedn´ım z n´asleduj´ıc´ıch zp˚ usob˚ u: if (vyraz) prikaz; if (vyraz) { prikazy; }
//jednoduchy prikaz
//blok
Prvn´ı z´apis pˇredstavuje variantu s jednoduch´ ym pˇr´ıkazem, druh´ y z´apis variantu s blokem. Ne´ uplnou podm´ınku lze interpretovat takto: Pokud v´ yraz (booleovsk´ y) nab´ yv´a pravdiv´e hodnoty, provede se pˇr´ıkaz resp. blok pˇr´ıkaz˚ u. Zopakujme znovu, ˇze blok nesm´ı b´ yt ukonˇcen stˇredn´ıkem. V praxi plat´ı z´asada, ˇze do bloku d´av´ame i jednoduch´ y pˇr´ıkaz, program se st´av´a ˇcitelnˇejˇs´ım. Pokud je to moˇzn´e, podm´ınky neuv´ad´ıme v negaci, ale v “kladn´e” formˇe. ´ ´ Upln´ a podm´ınka. Upln´ a podm´ınka vznikne rozˇs´ıˇren´ım ne´ upln´e podm´ınky o konstrukci else, kter´ a bude ´ provedena, pokud podm´ınka nebude splnˇena. Uplnou podm´ınku lze zapsat jedn´ım z n´asleduj´ıc´ıch zp˚ usob˚ u popˇr. je kombinovat:
34
ˇ ´I PROGRAMU A OPAKOVAN ´ ´I KAPITOLA 4. VETVEN if (vyraz) prikaz; else prikaz; if (vyraz) { prikazy; } else { prikazy; }
//jednoduchy prikaz
//blok //nelze pouzit strednik
V pˇr´ıpadˇe uˇzit´ı jednoduch´eho pˇr´ıkazu nesm´ıme pˇred else zapomenout na stˇredn´ık, u bloku pˇred else stˇredn´ık pouˇz´ıt naopak nem˚ uˇzeme. Lze vytv´ aˇret i sloˇzitˇejˇs´ı konstrukce, pˇri kter´ ych mohou b´ yt uvnitˇr podm´ınky vnoˇren´e dalˇs´ı bloky obsahuj´ıc´ı podm´ınky. V takov´em pˇr´ıpadˇe else odpov´ıd´ a nejbliˇzˇs´ımu nesp´ arovan´emu if. Konstrukci if (vyraz1) prikaz1 if (vyraz2)prikaz3 else prikaz4; else prikaz2; lze ch´ apat jako if (vyraz1) { prikaz1; if (vyraz2) { prikaz3; } else //odpovida nejblizsimu if { prikaz4; } } else { prikaz2; }
4.1.2
Oper´ ator ?
Tento oper´ ator naz´ yv´ ame tern´ arn´ım, m´ a tˇri argumenty. Umoˇzn ˇuje zapsat u ´plnou podm´ınku struˇcnˇejˇs´ım, avˇsak m´enˇe pˇrehledn´ ym, zp˚ usobem. Jeho syntaxe je Vyraz? Prikaz1: Prikaz2; Je -li v´ yraz vyhodnocen jako pravdiv´ y, je proveden Prikaz1, v opaˇcn´em pˇr´ıpadˇe Prikaz2. Podm´ınku
ˇ ´I PROGRAMU A OPAKOVAN ´ ´I KAPITOLA 4. VETVEN if (a
4.1.3
Pˇ r´ıkaz switch
Pˇr´ıkaz switch pˇredstavuje pˇrep´ınaˇc, kter´ y umoˇzn´ı vˇetven´ı programu do v´ıce vˇetv´ı. Poˇcet vˇetv´ı nen´ı omezen, m˚ uˇze b´ yt libovoln´ y. V kaˇzd´e vˇetvi se m˚ uˇze vyskytovat v´ıce pˇr´ıkaz˚ u, nemus´ı b´ yt uvedeny v bloku. Strukturu pˇr´ıkazu switch lze zjednoduˇsenˇe zapsat takto: switch(vyraz) { case konstanta1: Prikaz1; break; case konstanta2: Prikaz2; break; ... default PrikazX; } Syntaxe pˇr´ıkazu je pomˇernˇe sloˇzit´ a, uved’me jej´ı struˇcn´e vysvˇetlen´ı. Za pˇr´ıkazem switch je uveden v´ yraz, jehoˇz vyhodnocen´ım mus´ı vzniknout celoˇc´ıseln´ a hodnota. Tˇelo pˇr´ıkazu tvoˇr´ı tzv. n´ avˇeˇst´ı se syntax´ı case konstanta, kde konstanta pˇredstavuje celoˇc´ıselnou nebo znakovou konstantu. Za n´ avˇeˇst´ım jsou uvedeny pˇr´ıkazy, kter´e mohou b´ yt provedeny. Nejprve je vyhodnocena hodnota v´ yrazu. Pot´e je vybr´ ano takov´e n´ avˇeˇst´ı, jehoˇz konstanta m´ a stejnou hodnotu jako v´ yraz. N´aslednˇe se vykon´ a pˇr´ıkaz um´ıstˇen´ y za t´ımto n´ avˇeˇst´ım. Pokud nen´ı nalezeno odpov´ıdaj´ıc´ı n´avˇeˇst´ı, je vykon´ an k´od nach´ azej´ıc´ı se za n´ avˇeˇst´ım default. N´ avˇeˇst´ı default je vˇsak nepovinn´e, nemus´ı b´ yt uvedeno. Pˇr´ıkaz break je pˇr´ıtomen proto, aby umoˇznil pˇredˇcasn´e ukonˇcen´ı vykon´ av´ an´ı tˇela pˇr´ıkazu switch. Nebyl -li by uveden, v opaˇcn´em pˇr´ıpadˇe by doˇslo k proveden´ı vˇsech n´ asleduj´ıc´ıch vˇetv´ı bez ohledu na hodnoty n´avˇeˇst´ı za pˇr´ıkazy case. Uved’me pro u ´ plnost, ˇze ˇz´ adn´ a z konstant se v pˇr´ıkazu nesm´ı opakovat. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad ilustruj´ıc´ı pouˇzit´ı pˇr´ıkazu switch. switch(znak) { case ’1’: a++; a*=; break; case ’2’: a--; a/=; break; default: a*=; break; }
ˇ ´I PROGRAMU A OPAKOVAN ´ ´I KAPITOLA 4. VETVEN Na z´ avˇer uved’me pˇr´ıklad ilustruj´ıc´ı pouˇz´ıv´ an´ı podm´ınek pˇri ˇreˇsen´ı kvadratick´e rovnice. import java.math.*; public class rovnice { public static void main (String [] args) { double x1, x2, a=1, b=2, c=3; double diskr=b*b-4*a*c; if (diskr>0) { x1=-b+Math.sqrt(diskr)/(2*a); x2=-b/Math.sqrt(diskr)/(2*a); System.out.printnln("x1:"+x1); System.out.printnln("x2:"+x2); } else if (diskr==0) { x1=-b/(2*a); System.out.printnln("x1=x2:"+x1); } else System.out.printnln("Nema reseni"); } }
4.2
Pˇ rehled pˇ r´ıkaz˚ u pro opakov´ an´ı
Tyto pˇr´ıkazy naz´ yvan´e cykly umoˇzn ˇuj´ı prov´ adˇet opakov´ an´ı jednoho nebo v´ıce pˇr´ıkaz˚ u tvoˇr´ıc´ıch tzv. tˇelo cyklu. Opakov´ an´ı (tzv. iterace) je prov´ adˇeno na z´ akladˇe vyhodnocov´ an´ı logick´eho v´ yrazu nazvan´eho podm´ınka opakov´ an´ı. V Javˇe existuj´ı tˇri z´ akladn´ı typy cykl˚ u: cyklus for, cyklus while, cyklus do while. Pˇri konstrukci podm´ınky opakov´ an´ı mus´ıme d´ avat pozor, aby nevznikl nekoneˇcn´ y cyklus, kter´ y by prob´ıhal neust´ ale bez moˇznosti ukonˇcen´ı tˇela cyklu.
4.2.1
Cyklus while
Cyklus while obsahuje vyhodnocuje podm´ınku opakov´ an´ı pˇred pr˚ uchodem cyklu. Pokud je pravdiv´ a, je provedeno tˇelo cyklu. Pouˇz´ıv´ ame ho v pˇr´ıpadech, kdy nev´ıme, kolikr´ at opakov´ an´ı probˇehne. Jeho syntaxi lze zapsat takto while (vyraz) telo prikazu; Tˇelo pˇr´ıkazu nemus´ı probˇehnout ani jednou, pokud je v´ yraz napoprv´e vyhodnocen jako false. V tˇele cyklu mus´ı b´ yt modifikov´ ana promˇenn´ a ovlivˇ nuj´ıc´ı hodnotu v´ yrazu, jinak by vznikl nekoneˇcn´ y cyklus. N´ asleduj´ıc´ı pˇr´ıklad ukazuje v´ ypoˇcet faktori´ alu za pouˇzit´ı cyklu while, hodnota je pˇreˇctena ze standardn´ıho vstupu. public class faktorial {
ˇ ´I PROGRAMU A OPAKOVAN ´ ´I KAPITOLA 4. VETVEN public static void main (String [] args) { int cislo, f; f=1; byte [] pole=new byte [30]; System.out.println ("Zadejte cislo"); System.in.read(pole); String retezec=new String(pole); retezec=retezec.trim(); int cislo=(int)Long.parseLong(retezec); while (cislo>0) { f=f*cislo; cislo--; } System.out.println(cislo+"!="f); } }
4.2.2
Cyklus for
Cyklus for je pouˇz´ıv´ an v pˇr´ıpadech, kdy zn´ ame u ´daje o v´ ychoz´ı a koncov´e hodnotˇe testovac´ıho v´ yrazu. Syntaxi cyklu for lze zapsat for (inicializacni_vyraz; testovaci_vyraz; zmenovy_vyraz) telo_prikazu Inicializaˇcn´ı v´ yraz je vykon´ an pouze jednou, a to jeˇstˇe pˇred vyhodnocen´ım testovac´ıho v´ yrazu. Testovac´ı v´ yraz urˇcuje, zda se m´ a prov´est tˇelo cyklu. Tˇelo cyklu se prov´ ad´ı tak dlouho, dokud je testovac´ı v´ yraz vyhodnocen jako pravdiv´ y. Zmˇenov´ y v´ yraz se vyhodnot´ı na konci cyklu po vykon´ an´ı tˇela cyklu, pouˇz´ıv´ a se pro zmˇenu hodnoty testovac´ıho v´ yrazu. Inicializaˇcn´ı, testovac´ı i zmˇenov´ y v´ yraz jsou nepovinn´e, nemus´ı b´ yt uv´adˇeny. Pod´ıvejme se na nˇekter´e pˇr´ıklady. Nejˇcastˇeji je prov´ adˇena deklarace s inicializac´ı pˇr´ımo v hlaviˇcce cyklu for. for (int i=0;i<10;i++) System.out.println(i); Deklarace m˚ uˇze b´ yt provedena mimo cyklus, inicializace v cyklu. int i; for (i=0;i<10;i++) System.out.println(i); Mimo cyklus mohou b´ yt um´ıstˇeny deklarace i inicializace. V tom pˇr´ıpadˇe je nutno prov´ adˇet zmˇenu hodnoty testovac´ıho v´ yrazu v tˇele cyklu, jinak by vznikl nekoneˇcn´ y cyklus. int i=0; for (;i<10;i++) System.out.println(i++); Lze vytvoˇrit cyklus s pr´ azdn´ ym tˇelem, kdy souˇc´ ast´ı zmˇenov´eho v´ yrazu bude i v´ ykonn´ y k´ od. int i=0; for (;i<10;System.out.println(i++);
ˇ ´I PROGRAMU A OPAKOVAN ´ ´I KAPITOLA 4. VETVEN M˚ uˇze vytvoˇrit i minimalistickou variantu cyklu vyuˇz´ıvaj´ıc´ı stejnˇe jako pˇr´ıkaz switch k pˇredˇcasn´emu ukonˇcen´ı cyklu pˇr´ıkaz break. int i=0; for (; ; ;) { if (i<10) System.out.println(i++); else break; } Posledn´ı tˇri konstrukce sp´ıˇse ilustruj´ı moˇznosti pouˇz´ıv´ an´ı cyklu for, v praxi nejsou pˇr´ıliˇs ˇcasto pouˇz´ıv´any, z´ apis nen´ı pˇrehledn´ y. V cyklu for m˚ uˇzeme pouˇz´ıvat v´ıce inicializaˇcn´ıch, testovac´ıch a zmˇenov´ ych v´ yraz˚ u, kter´e jsou oddˇeleny oper´ atorem ˇc´ arka. int i, j; for (i=0, j=0;i<10;i++,j++) { System.out.println(i); System.out.println(j); } Deklarace obou promˇenn´ ych je nutno v takov´em pˇr´ıpadˇe prov´est vnˇe cyklu. Nen´ı vhodn´e, aby byly hodnoty promˇenn´ ych zmˇenov´eho v´ yrazu na sobˇe vz´ ajemnˇe z´ avisl´e. int i, j; for (i=0, j=0;i<10, j<20;i++,j=3*i) { System.out.println(i); System.out.println(j); } V takov´em pˇr´ıpadˇe je pomˇernˇe obt´ıˇzn´e na prvn´ı pohled stanovit hodnoty zmˇenov´ ych v´ yraz˚ u.
4.2.3
Cyklus do while
Tento cyklus se od v´ yˇse uveden´ ych cykl˚ u liˇs´ı t´ım, ˇze je podm´ınka testov´ ana aˇz po vykon´ an´ı tˇela cyklu. Cyklus proto probˇehne vˇzdy nejm´enˇe jedenkr´ at. Pouˇz´ıv´ a se opˇet nejˇcastˇeji v pˇr´ıpadˇe, kdy pˇresnˇe nev´ıme, kolikr´at m´ a cyklus probˇehnout (ale mˇel by probˇehnout alespoˇ n jednou). Jeho syntaxi lze zapsat takto do telo_cyklu while testovaci_vyraz
4.2.4
Vnoˇ ren´ e cykly
Pˇri sloˇzitˇejˇs´ıch v´ ypoˇctech jsou ˇcasto pouˇz´ıv´ any vnoˇren´e cykly, typick´ ym pˇr´ıkladem je pr´ ace napˇr. s maticemi. Vnoˇren´ y cyklus si m˚ uˇzeme pˇredstavit jako cyklus nach´ azej´ıc´ı se v jin´em cyklu. for (int i=0;i<10;i++) for (int j=0;j<10;j++) System.out.println(i*j);
ˇ ´I PROGRAMU A OPAKOVAN ´ ´I KAPITOLA 4. VETVEN
4.2.5
Pˇ r´ıkaz break
Pˇr´ıkaz break, se kter´ ym jsme se jiˇz setkali, umoˇzn ˇuje okamˇzitˇe ukonˇcit prov´ adˇen´ı tˇela cyklu. Lze se setkat se dvˇema variantami z´ apisu break; break navesti; Prvn´ı moˇznost umoˇzn ˇuje “vyskoˇcit” z cyklu, v jehoˇz tˇele je tento k´ od zaps´ an. Druh´ a varianta provede ukonˇcen´ı prov´ adˇen´ı cyklu oznaˇcen´eho n´ avˇeˇst´ım. Nach´ az´ı -li se pˇr´ıkay v nˇejak´em vnoˇren´em cyklu, m˚ uˇzeme vyskoˇcit i o nˇekolik u ´rovn´ı v´ yˇse. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad. Vyskoc: //nazev navesti for (int i=0;i<10;i++) { for (int j=0;j<10;j++) { if (i==j+10) { System.out.println(i*j); break Vyskoc; //Ukonceni cyklu v navesti Vyskoc k=i+j; } } }
4.2.6
Pˇ r´ıkaz continue
Pˇr´ıkaz continue slouˇz´ı k pˇreskoˇcen´ı zb´ yvaj´ıc´ı ˇc´ asti pˇr´ıkaz˚ u nach´ azej´ıc´ıch se v tˇele cyklu a k pˇrechodu na dalˇs´ı iteraci. Stejnˇe jako pˇr´ıkaz break existuje ve dvou variant´ ach. continue; continue navesti; Prvn´ı varianta zp˚ usob´ı vynech´ an´ı vˇsech pˇr´ıkaz˚ u a skok na dalˇs´ı iteraci. for (int i=0;i<10;i++) { for (int j=0;j<10;j++) { if (i==j+10) { System.out.println(i*j); continue; k++; } } }
ˇ ´I PROGRAMU A OPAKOVAN ´ ´I KAPITOLA 4. VETVEN Druh´ a varianta umoˇzn ˇuje pˇreskoˇcen´ı ˇc´ asti cyklu, kter´ a je oznaˇcena t´ımto n´ avˇeˇst´ım. Tato konstrukce se vˇsak v praxi pˇr´ıliˇs ˇcasto nepouˇz´ıv´ a. Pod´ıvejme se na pˇr´ıklad ilustruj´ıc´ı pouˇz´ıv´ an´ı cykl˚ u ve spolupr´ aci s poli prov´ adˇej´ıc´ı hled´ an´ı maxim´ aln´ı hodnoty ze zadan´ ych ˇc´ısel. Vytvoˇr´ıme inicializovan´e pole, kter´e budeme proch´ azet za pouˇzit´ı cyklu for. public class Maximum { public static void main (String [] args) { int [] pole={3,67,32,6,33,0,5,76,54,4}; int max=pole[0]; for(int i=0;i<pole.length;i++) { if(pole[i]>max) max=pole[i]; } System.out.println("Max.="+max); } }
Kapitola 5
Objekty, tˇ r´ıdy, metody Objektovˇe orientovan´e programov´ an´ı (OOP) pˇredstavuje metodick´ y postup ˇreˇsen´ı probl´emu. Na rozd´ıl od procedur´aln´ıho programov´ an´ı v´ azan´eho na algoritmus umoˇzn ˇuje (OOP) popis probl´emu realizovat komplexnˇeji a efektivnˇeji. S objektovˇe orientovan´ ym pˇr´ıstupem k ˇreˇsen´ı probl´emu souvisej´ı dva pojmy: objekt a tˇr´ıda. V t´eto kapitole se sezn´ am´ıme se z´ aklady objektovˇe orientovan´eho programov´an´ı v jazyce Java. Nauˇc´ıme se deklarovat tˇr´ıdy, vytv´ aˇret objekty, pouˇz´ıvat metody. Objekty v programovac´ım jazyce pˇredstavuj´ı nehmotnou analogi´ı objekt˚ u, kter´e n´as obklopuj´ı v re´aln´em svˇetˇe. Kaˇzd´ y z objekt˚ u m´ a urˇcit´e vlastnosti a chov´an´ı. Vlastnosti objektu jsou ovlivnˇeny daty, chov´an´ı objektu pak metodami, kter´e objekty pouˇz´ıvaj´ı pro vz´ajemnou komunikaci. Objekty spolu mohou komunikovat pˇres rozhran´ı.
5.1
Metody
Metoda patˇr´ı mezi nejˇcastˇeji pouˇz´ıvan´e konstrukce programovac´ıho jazyka. Pˇredstavuje samostatnou ˇc´ast programu konaj´ıc´ı nˇejakou specializovanou funkci. Metody jsou um´ıstˇeny mimo hlavn´ı program, mohou b´ yt spouˇstˇeny z metody main() nebo z jak´ekoliv jin´e metody. Metodu zpravidla vol´ame se seznamem parametr˚ u, kter´ ym pˇred´av´ ame hodnoty potˇrebn´e pro v´ ypoˇcet, metoda vˇetˇsinou vrac´ı nˇejak´ y v´ ysledek. Existuj´ı i metody, kter´ ym nepˇred´ av´ ame ˇz´ adn´e u ´daje, nebo naopak ˇz´adn´e v´ ysledky nevrac´ı. V´ yhodou jejich pouˇz´ıv´ an´ı je zjednoduˇsen´ı struktury zdrojov´eho k´odu ˇci moˇznost opakovan´eho prov´adˇen´ı v´ ypoˇct˚ u (tj. nemus´ıme ps´ at znovu cel´ y k´ od, pouze zavol´ame pˇr´ısluˇsnou metodu). Z hlediska OOP lze metody ch´apat jako zpr´ avy zaslan´e instanc´ım nebo tˇr´ıd´am. Metody b´ yvaj´ı nˇekdy oznaˇcov´any jako funkce ˇci podprogramy, ale toto oznaˇcen´ı nen´ı pˇresn´e. Dˇ elen´ı metod: Metody dˇel´ıme do dvou skupin: • metody tˇr´ıdy (statick´e metody). • metody instance. Nejprve se sezn´ am´ıme s prvn´ı skupinou metod. Vˇetˇsinu z´ıskan´ ych poznatk˚ u lze n´aslednˇe aplikovat i na metody instance.
42
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR
5.1.1
Metody tˇ r´ıdy
Metody tˇr´ıdy pˇredstavuj´ı zpr´ avy zaslan´e tˇr´ıdˇe jako celku, nelze je volat pro konkr´etn´ı instanci. Mohou b´ yt pouˇz´ıv´any v pˇr´ıpadech, kdy jeˇstˇe neexistuje ˇz´ adn´ a instance tˇr´ıdy. Metody tˇr´ıdy b´ yvaj´ı oznaˇcov´ any jako statick´e metody. Ve statick´ ych metod´ ach lze pouˇz´ıvat pouze statick´e promˇenn´e nebo lok´ aln´ı promˇenn´e, nemohou v nich b´ yt pouˇz´ıv´ any promˇenn´e instance. Statick´e metody jsou v Javˇe pouˇz´ıv´ any pˇri matematick´ ych v´ ypoˇctech: napˇr. Math.sin(x) pˇredstavuje statickou metodu tˇr´ıdy Math. Deklarace a vol´ an´ı metody Deklarace metody je tvoˇrena hlaviˇckou metody a tˇelem metody. Hlaviˇcka obsahuje informaci o jm´enu metody, typu n´ avratov´e hodnoty, seznam form´ aln´ıch parametr˚ u. Jm´eno metody je zpravidla ps´ ano mal´ ymi p´ısmeny, mˇelo by vyjadˇrovat ˇcinnost metody. //Deklarace metody tridy static navratovy_typ jmeno_metody(typ form_param1, typ form_param2,...) //Hlavicka { //Telo metody } Tˇelo metody tvoˇr´ı v´ ykonn´ y k´od um´ıstˇen´ y uvnitˇr sloˇzen´ ych z´ avorek. Metody tˇr´ıdy jsou deklarov´ any s kl´ıˇcov´ ym slovem static. Uved’me, ˇze na rozd´ıl od jazyka C++ nemus´ıme vytv´ aˇret prototyp funkce. V Javˇe nen´ı podstatn´e, zda vol´ an´ı metody pˇredch´ az´ı jej´ı deklaraci ˇci naopak. jmeno_metody(skut_param1, skut_param2,...) //Volani metody Pod´ıvejme se ponˇekud podrobnˇeji na problematiku parametr˚ u metod. Vysvˇetleme pojmy form´ aln´ı parametry metod a skuteˇcn´e parametry metod. Form´ aln´ı parametry. Deklaraci form´ aln´ıch parametr˚ u nalezneme v hlaviˇcce metody. Stejnˇe, jako jak´ekoliv jin´ a promˇenn´ a, mus´ı b´ yt i form´ aln´ı parametr deklarov´ an s uveden´ım datov´eho typu a n´ azvu. Skuteˇ cn´ e parametry. Skuteˇcn´e parametry pouˇz´ıv´ ame pˇri vol´ an´ı metody, s hodnotami tˇechto parametr˚ u metodu vol´ ame. Skuteˇcn´e parametry by mˇely b´ yt stejn´eho datov´eho typu jako parametry form´ aln´ı. Nejsou -li, je provedena implicitn´ı konverze (pokud je to moˇzn´e). Pˇ red´ av´ an´ı parametr˚ u hodnotou. V Javˇe jsou pˇred´ av´ any parametry primitivn´ıch datov´ ych typ˚ u hodnotou. Form´aln´ı parametr pˇredstavuje kopii skuteˇcn´eho parametru. Jak´ akoliv zmˇena hodnoty form´aln´ıho parametru neovlivn´ı hodnotu skuteˇcn´eho parametru. Pˇred´ av´ an´ı hodnot skuteˇcn´ ych parametr˚ u parametr˚ um form´ aln´ım je prov´ adˇeno pˇri vol´ an´ı metody. Hodnoty jsou pˇred´ av´ any postupnˇe, tj. hodnotˇe prvn´ıho form´ aln´ıho parametru je pˇred´ ana hodnota prvn´ıho skuteˇcn´eho parametru, hodnotˇe druh´eho form´ aln´ıho parametru hodnota druh´eho skuteˇcn´eho parametru, atd... form_param1=skut_param1; form_param2=skut_param2; ...
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR N´ avratov´ y typ. Pokud metoda nevrac´ı ˇz´ adnou hodnotu, je jej´ı n´ avratov´ y typ void. M´ a -li metoda n´avratovou hodnotu (tj. jej´ı n´ avratov´ a hodnota je jin´eho typu neˇz void), mus´ı metoda obsahovat kl´ıˇcov´e slovo return s uveden´ım hodnoty ˇci v´ yrazu, kter´ y bude metoda navracet jako v´ ysledek. D´ ale jiˇz nesm´ı n´ asledovat ˇz´ adn´ y k´od, byl by nedostupn´ y, tzv. unreachable k´ od. Metoda v Javˇe je schopna vr´atit nejv´ yˇse jednu hodnotu. Nelze tedy vytvoˇrit metodu, kter´ a by pˇr´ımo vracela dvˇe hodnoty. Toto omezen´ı lze “obej´ıt” pˇred´ av´ an´ım parametr˚ u odkazem (viz d´ ale) ˇci pˇredat metodˇe jako parametr sloˇzitˇejˇs´ı strukturu, do kter´e budou v´ ysledky uloˇzeny. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad, metoda obvod() slouˇz´ı k v´ ypoˇctu obvodu kruhu. static double obvod (double r)// formalni parametr r { return 2*Math.PI*r; } Pokud je tˇelo metody “kr´ atk´e”, lze metodu zapsat do jednoho ˇr´ adku static double obvod (double r){return 2*Math.PI*r;} Metoda m´a jeden form´ aln´ı parametr typu double, vrac´ı tak´e hodnotu typu double: za kl´ıˇcov´ ym slovem return n´asleduje v´ ypoˇcet 2πr. Metodu vol´ ame z ”hlavn´ıho” programu uveden´ım jej´ıho n´ azvu a seznamu skuteˇcn´ ych parametr˚ u v kulat´ ych z´ avork´ ach. public class kruh { //deklarace metody obvod static double obvod (double r) { return 2*Math.PI*r; } //deklarace metody main public static void main (String [] args) { double pol=50; //volani metody obvod se skutecnym parametrem pol double obv=obvod(pol); System.out.println(obv); } } Pˇ red´ av´ an´ı parametr˚ u odkazem. V Javˇe existuje moˇznost pˇred´ av´ an´ı parametr˚ u odkazem. T´ yk´ a se pouze neprimitivn´ıch datov´ ych typ˚ u, tj. pol´ı a objekt˚ u. V takov´em pˇr´ıpadˇe zmˇena hodnoty form´ aln´ıho parametru zp˚ usob´ı zmˇenu hodnoty skuteˇcn´eho parametru. Pˇri pˇred´ av´ an´ı nevznik´ a kopie pole ˇci objektu, ale kopie odkazu na pole ˇci objekt. static navratovy_typ jmeno_metody(obj_typ form_param1, obj_typ form_param2,...) { form_param1=... //Zmena form. parametru->zmenu skut. parametru }
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR Jednoduch´ ym pˇr´ıkladem ilustruj´ıc´ım pˇred´ av´ an´ı parametr˚ u odkazem je tˇr´ıdˇen´ı. Metodˇe pˇred´ av´ ame nesetˇr´ıdˇen´e pole, kter´e je v tˇele metody setˇr´ıdˇeno. Na n´ asleduj´ı uk´ azce je pˇr´ıklad tˇr´ıd´ıc´ıho algoritmu Bubble Sort. void bubbleSort(double x []) //formalnim parametrem odkaz na pole { for (int i=0;i<x.length;i++) { for (int j=x.length-1;j>i;j--) { if (x[j]<x[j-1]) { double pom=x[j] //Lokalni promenna x[j]=x[j-1] //Modifikace pole x[j-1]=pom //Modifikace pole } } } } Lok´ aln´ı promˇ enn´ e. V metod´ ach mohou b´ yt deklarov´ any lok´ aln´ı promˇenn´e. Princip deklarace je stejn´ y, jako by se jednalo o ”bˇeˇznou promˇennou”. Lok´ aln´ı promˇenn´e vznikaj´ı pˇri vol´ an´ı metody a zanikaj´ı po jej´ım ukonˇcen´ı. Na rozd´ıl od datov´ ych poloˇzek tˇr´ıdy nen´ı prov´ adˇena jejich automatick´ a inicializace, kompil´ator vˇsak kontroluje, zda lok´ aln´ı promˇenn´ a byla inicializov´ ana. Hodnoty lok´ aln´ıch promˇenn´ ych z pˇredchoz´ıch vol´ an´ı metod se neuchov´ avaj´ı. Metoda bez n´ avratov´ e hodnoty V praxi jsou tyto metody pomˇernˇe ˇcasto pouˇz´ıv´ any, b´ yvaj´ı naz´ yv´ any procedurami. Jejich n´ avratov´ y typ je void. Takov´e metody slouˇz´ı napˇr. pro realizaci vstupn´ıch ˇci v´ ystupn´ıch operac´ı (tj. tiskov´e v´ ystupy). static void tisk () { System.out.println("Obvod je:"+obv+" m"); } Metody s v´ıce parametry Metodˇe lze pˇredat v´ıce neˇz jeden parametr, parametry nav´ıc mohou b´ yt r˚ uzn´eho datov´eho typu. Jejich poˇcet by vˇsak nemˇel b´ yt pˇr´ıliˇs velk´ y (cca 5), takov´ a metoda se st´ av´ a nepˇrehlednou. Na prvn´ı pohled nen´ı jasn´e, kter´ a data do v´ ypoˇctu vstupuj´ı. Pod´ıvejme se na pˇr´ıklad prov´ adˇej´ıc´ı v´ ypoˇcet odvˇesny v pravo´ uhl´em troj´ uheln´ıku za pouˇzit´ı Pythagorovy vˇety. static double pythagoras (double a , double b) { return Math.sqrt(a*a+b*b); } Metodu pythagoras() lze volat napˇr. takto double prepona=pythagoras(odvesna1, odvesna2);
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR
5.1.2
Implicitn´ı a explicitn´ı konverze.
Zamˇeˇrme se podrobnˇeji na problematiku implicitn´ı a explicitn´ı konverze mezi skuteˇcn´ ymi a form´ aln´ımi parametry. Pokud je n´ avratov´ y typ metody odliˇsn´ y od typu n´ avratov´e hodnoty, je prov´ adˇena bud’ implicitn´ı konverze nebo explicitn´ı konverze. Implicitn´ı konverze je prov´ adˇena kompil´ atorem automaticky, uˇzivatel si ji v podstatˇe ani nevˇsimne, viz n´ asleduj´ıc´ı pˇr´ıklad. static double pythagoras (int a , int b) { double vysledek; vysledek=Math.sqrt(a*a+b*b);//rozsirujici konverze return vysledek; } Jak v´ıme, pˇri implicitn´ı konverzi doch´ az´ı ke konverzi datov´eho typu s niˇzˇs´ım rozsahem na datov´ y typ s vyˇsˇs´ım rozsahem,nem˚ uˇze pˇri n´ı doj´ıt ke ztr´ atˇe pˇresnosti. Explicitn´ı konverze mus´ı b´ yt provedena uˇzivatelem, d˚ uvodem je moˇznost ztr´ aty pˇresnosti dat pˇri konverzi datov´eho typu s vyˇsˇs´ım rozsahem na datov´ y typ s niˇzˇs´ım rozsahem, v opaˇcn´em pˇr´ıpadˇe nebude moˇzno zdrojov´ y k´ od zkompilovat. static int pythagoras (double a , double b) { double vysledek; vysledek=Math.sqrt(a*a+b*b); return (int) vysledek; //zuzujici konverze }
5.1.3
Rekurzivn´ı metody
Rekurze je schopnost metody, datov´e struktury ˇci objektu volat sebe sama nebo volat metodu, datovou strukturu ˇci objekt podobn´eho typu. Tento pˇr´ıstup se ˇcasto uplatˇ nuje pˇri ˇreˇsen´ı nˇekter´ ych u ´ loh. Takov´ ym typ˚ um probl´em˚ u se ˇr´ık´ a dekomponovateln´e, mohou b´ yt rozloˇzeny na podprobl´emy stejn´eho nebo podobn´eho typu nad menˇs´ı mnoˇzinou dat. Rekurzivnˇe lze volat kaˇzdou metodu s v´ yjimkou metody main(). Rekurzivn´ı algoritmus mus´ı obsahovat podm´ınku, pˇri kter´e dojde k jej´ımu ukonˇcen´ı, aby nepokraˇcovala do nekoneˇcna. V opaˇcn´em pˇr´ıpadˇe bychom hovoˇrili o tzv. nekoneˇcn´e rekurzi. V urˇcit´em m´ıstˇe tedy mus´ı doj´ıt k takov´emu doˇreˇsen´ı probl´emu, kter´e nebude rekurzivn´ı. Pˇri kaˇzd´em nov´em vol´ an´ı doch´ az´ı k vytvoˇren´ı nov´ ych lok´ aln´ıch promˇenn´ ych (tato vlastnost je souˇcasnˇe nev´ yhodou rekurze). Pot´e jsou zpˇetnˇe dopoˇc´ıt´ av´ any hodnoty z pˇredchoz´ıch vol´ an´ı metod. Typick´ y pˇr´ıklad pouˇzit´ı rekurze pˇredstavuje faktori´ al. static int fakt(int n) { if (n>1) return n*fakt(n-1); else return 1; } Metodu lze volat napˇr. takto: int cislo=10; int faktorial=fakt(cislo); Rekurzivn´ı postupy nejsou vˇzdy v´ yhodn´e, typick´ ym pˇr´ıkladem je v´ ypoˇcet Fibonacciho posloupnosti.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR
5.1.4
Pˇ retˇ eˇ zov´ an´ı metod
Pˇretˇeˇzov´ an´ı metod je jedn´ım ze z´ akladn´ıch rys˚ u OOP. Umoˇzn ˇuje deklarovat v´ıce metod stejn´eho n´ azvu, kter´e se mohou liˇsit r˚ uzn´ ym poˇctem, typem argument˚ u popˇr. jejich poˇrad´ım. Postup se pouˇz´ıv´ a nejˇcastˇeji u metod prov´ adˇej´ıc´ıch stejn´e ˇcinnosti, ale s r˚ uzn´ ymi typy dat. Pokud zavol´ ame pˇret´ıˇzenou metodu, kompil´ ator na z´ akladˇe typu parametr˚ u, jejich poˇrad´ı ˇci poˇctu vybere “spr´ avnou” metodu. Pod´ıvejme se na pˇret´ıˇzenou metodu vzdalenost(), prov´ adˇej´ıc´ı v´ ypoˇcet vzd´ alenosti mezi body zadan´e pravo´ uhl´ ymi souˇradnicemi, souˇradnicov´ ymi rozd´ıly popˇr. kombinac´ı obou parametr˚ u. static double vzdalenost(double x1, double y1, double x2, double y2) { return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); } static double vzdalenost(double dx, double dy) { return Math.sqrt(dx*dy+dy*dy); } static int vzdalenost(int x1, int y1, int x2, int y2) { return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); } Pokud budeme volat metodu vzdalenost() s n´ asleduj´ıc´ıcmi parametry double vzd=vzdalenost(1.0,0.0,6.0,0.0); obdrˇz´ıme v´ ysledek 5.0, bude provedena prvn´ı metoda. Pokud budeme volat metodu vzdalenost() s n´asleduj´ıc´ımi parametry double vzd=vzdalenost(1,0,6,0); obdrˇz´ıme v´ ysledek 5, bude provedena tˇret´ı metoda. Pokud budeme volat metodu vzdalenost() s n´ asleduj´ıc´ımi parametry double vzd=vzdalenost(5.0,0.0); bude provedena druh´ a metoda, obdrˇz´ıme v´ ysledek 5.0.
5.2
Tˇ r´ıdy
Tˇr´ıda pˇredstavuje vzor, prostˇrednictv´ım kter´eho lze vytv´ aˇret objekty. Objekty nˇekdy tak´e naz´ yv´ ame instancemi tˇr´ıdy. Tyto pojmy se ˇcasto vz´ ajemnˇe zamˇen ˇuj´ı. V programovac´ım jazyce Java je k´ od um´ıstˇen uvnitˇr tˇr´ıdy, tj. v bloku s jej´ı deklarac´ı. Kaˇzd´ y program mus´ı m´ıt minim´ alnˇe jednu tˇr´ıdu.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR Modifik´ ator public abstract final
Popis Veˇrejn´ a tˇr´ıda. Pˇr´ıstupn´ a i mimo bal´ıˇcek, ve kter´em byla deklarov´ ana. Nejˇcastˇeji pouˇz´ıvan´ a varianta. Abstraktn´ı tˇr´ıda. Od tˇr´ıdy nelze vytvoˇrit objekt. Fin´ aln´ı tˇr´ıda. Od tˇr´ıdy nelze odvodit potomky. Tabulka 5.1: Pˇrehled modifik´ ator˚ u pˇr´ıstupu ke komponent´ am tˇr´ıdy.
5.2.1
Deklarace tˇ r´ıdy
Deklarace tˇr´ıdy zaˇc´ın´ a kl´ıˇcov´ ym slovem class, pˇred n´ım se mohou vyskytovat tzv. modifik´ atory pˇr´ıstupu. Tˇelo tˇr´ıdy je uzavˇreno do sloˇzen´ ych z´ avorek a obsahuje zpravidla nˇejak´ y v´ ykonn´ y k´ od (analogie tˇela metod). Prozat´ım vynech´ ame pˇr´ıpady, kdy tˇr´ıda m˚ uˇze b´ yt potomkem jin´e tˇr´ıdy. S tˇemito situacemi se setk´ ame aˇz v kapitole vˇenovan´e jednoduch´e dˇediˇcnosti. N´ asleduj´ıc´ı deklarace tˇr´ıdy je oproti skuteˇcnosti ponˇekud zjednoduˇsen´ a, avˇsak pro prvn´ı sezn´ amen´ı s tˇr´ıdou dostaˇcuj´ıc´ı a pomˇernˇe n´ azorn´ a. modifik´ ator class identifikator { //kod } Vˇsimnˇeme si, ˇze na rozd´ıl od jazyka C++ nen´ı deklarace tˇr´ıdy ukonˇcena stˇredn´ıkem. Pˇ r´ıstup ke komponent´ am tˇ r´ıdy. Existuj´ı tˇri typy modifik´ ator˚ u, kter´e ovlivˇ nuj´ı pˇr´ıstup ke komponent´am tˇr´ıdy. Jejich popis uved’me zat´ım bez bliˇzˇs´ıho vysvˇetlov´ an´ı v tab. 5.1, dalˇs´ı podrobnosti se dozv´ıme aˇz v z´ avˇeru kapitoly. Pokud pˇred kl´ıˇcov´ ym slovem class nen´ı uveden ˇz´ adn´ y modifik´ ator, povaˇzujeme tˇr´ıdu za soukromou. Od takov´e tˇr´ıdy lze vytvoˇrit objekt, m˚ uˇze b´ yt rodiˇcovskou tˇr´ıdou. Nˇekter´e modifik´ atory lze vz´ ajemnˇe kombinovat, jsou povoleny kombinace 1+2 a 1+3.
5.2.2
Tˇ elo tˇ r´ıdy a pˇ r´ıstupov´ a pr´ ava
Tˇelo tˇr´ıdy je uzavˇreno do sloˇzen´ ych z´ avorek, nalezneme v nˇem deklarace ˇclen˚ u tˇr´ıdy, tj. datov´ ych poloˇzek a metod. Ke kaˇzd´e z nich je moˇzno nastavit pˇr´ıstupov´ a pr´ ava. V Javˇe existuj´ı ˇctyˇri z´ akladn´ı typy pˇr´ıstupov´ ych pr´ av; jsou podobn´ a pˇr´ıstupov´ ym pr´ av˚ um v jazyce C++, jejich pˇrehled nalezneme v tab. 5.2. Princip zapouzdˇ ren´ı. S aplikacemi pˇr´ıstupov´ ych pr´ av k jednotliv´ ym se budeme zab´ yvat v dalˇs´ım v´ ykladu. Zopakujme na tomto m´ıstˇe, ˇze pˇri n´ avrhu tˇr´ıdy je nutno dodrˇzovat princip zapouzdˇren´ı dat, kdy s datov´ ymi poloˇzkami mohou manipulovat pouze metody tˇr´ıdy. Mˇely by b´ yt proto deklarov´ any jako priv´atn´ı. Metody realizuj´ıc´ı rozhran´ı by mˇely b´ yt deklarov´ any jako veˇrejn´e, ostatn´ı metody mohou b´ yt deklarov´any jako priv´ atn´ı. Zajist´ıme tak autorizovan´ y pˇr´ıstup k dat˚ um. Zapouzdˇren´ı umoˇzn ˇuje pˇred ostatn´ımi objekty zatajit vnitˇrn´ı stav objektu. Pˇri n´ ahodn´ ych operac´ıch nemohou jin´e objekty mˇenit stav objektu pˇr´ımo a zan´est do nˇej nechtˇen´e chyby. Promˇenn´e instance nejsou z vnˇejˇsku pˇr´ımo viditeln´e, nem˚ uˇzeme s nimi pˇr´ımo manipulovat. Metody instance umoˇzn ˇuj´ı objektu komunikovat se sv´ ym okol´ım, pˇredstavuj´ı jeho rozhran´ı.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR Pˇr´ıst. pr´ avo public
private
protected
neuvedeno
Popis Veˇrejn´e ˇcleny. Mohou b´ yt pouˇzity kdekoliv: v jin´e tˇr´ıdˇe, v jin´em bal´ıku, mohou je pouˇz´ıvat i pˇr´ıpadn´ı potomci. Tyto ˇcleny pˇredstavuj´ı rozhran´ı, jako public deklarujeme metody, nikoliv promˇenn´e. Soukrom´e ˇcleny. Mohou b´ yt pouˇz´ıv´ any jen v metod´ ach tˇr´ıdy, do kter´e patˇr´ı. Nelze k nim pˇristoupit z vnˇejˇsku tˇr´ıdy. Jako private b´ yvaj´ı deklarov´ any promˇenn´e, t´ımto zp˚ usobem je realizov´ an princip zapouzdˇren´ı dat. Chr´ anˇen´e ˇcleny. Mohou b´ yt pouˇzity v metod´ ach tˇr´ıdy, kde vznikly, v metod´ ach jejich potomk˚ u a ve vˇsech tˇr´ıd´ ach t´ehoˇz bal´ıˇcku. Potomci nemus´ı b´ yt ve stejn´em bal´ıˇcku jako rodiˇcovsk´ a tˇr´ıda. Pˇr´ atelsk´e ˇcleny. Mohou b´ yt pouˇz´ıv´ any pouze v r´ amci bal´ıˇcku. Tabulka 5.2: Pˇrehled pˇr´ıstupov´ych pr´ av k jednotliv´ym ˇclen˚ um tˇr´ıdy.
N´ avrh tˇ r´ıdy. Pˇred n´ avrhem tˇr´ıdy je nutn´e peˇclivˇe zv´ aˇzit, jak´e metody a datov´e poloˇzky pouˇzijeme. Nevhodn´ a architektura tˇr´ıdy je kontraproduktivn´ı, m˚ uˇze v´est k omezeni funkˇcnosti k´ odu, poruˇsen´ı z´ asad objektovˇe orientovan´eho programov´ an´ı ˇci k obt´ıˇzn´emu udrˇzov´ an´ı k´ odu. N´ avrhu tˇr´ıdy je proto nutn´e vˇenovat velkou pozornost. Upozornˇeme, ˇze tˇr´ıda nemus´ı obsahovat metodu main(), v takov´em pˇr´ıpadˇe nebude moˇzn´e k´ od uvnitˇr tˇr´ıdy vykon´ avat pˇr´ımo. Postup pˇredvedeme na praktick´em pˇr´ıkladu. Vytvoˇr´ıme veˇrejnou tˇr´ıdu Souradnice, kter´ a umoˇzn ˇuje prov´adˇet pˇrevod pol´ arn´ıch souˇradnic na pravo´ uhl´e. public class Souradnice { private double delka, uhel; public double x () { return delka*Math.cos(180*uhel/Math.PI); } public double y () { return delka*Math.sin(180*uhel/Math.PI); } public static void main (String [] args) { //zatim zadny kod } } Tˇr´ıda souradnice obsahuje dvˇe datov´e poloˇzky, tj. promˇenn´e typu double, pˇredstavuj´ıc´ı pol´ arn´ı souˇradnice deklarovan´e jako private a dvˇe metody pro v´ ypoˇcet pravo´ uhl´ ych souˇradnic deklarovan´e jako public. Metoda main() zat´ım neobsahuje ˇz´ adn´ y v´ ykonn´ y k´ od, jej´ı tˇelo je pr´ azdn´e.
5.3
Operace s tˇ r´ıdami
Vyuˇzijme dosavadn´ıch znalost´ı o metod´ ach a pokus´ıme se je d´ ale rozˇs´ıˇrit. Na rozd´ıl od metody tˇr´ıdy je nutno pro metody instance vytvoˇrit nˇejak´ y objekt, se kter´ ym je budeme pouˇz´ıvat.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR
5.3.1
Vytvoˇ ren´ı objektu
Pro vytvoˇren´ı objektu (resp. instance) je nutno prov´est dva kroky: 1. Deklarace referenˇcn´ı promˇenn´e Tento krok pˇredstavuje vytvoˇren´ı odkazu na referenˇcn´ı promˇennou urˇcit´eho datov´eho typu. 2. Inicializace referenˇcn´ı promˇenn´e objektem Se samotn´ ym odkazem nen´ı moˇzno pracovat, doˇslo by k v´ yjimce. V dalˇs´ım kroku je nutno vytvoˇrit v pamˇeti nov´ y objekt a inicializovat j´ım vytvoˇrenou referenˇcn´ı promˇennou. Pokud objekt nen´ı stejn´eho typu jako referenˇcn´ı promˇenn´ a, je provedena implicitn´ı konverze. Nelze -li prov´est implicitn´ı konverzi, mus´ı b´ yt provedena konverze explicitn´ı (s tˇemito postupy se setk´ame v kapitole vˇenovan´e dˇediˇcnosti). Praktick´ y postup budeme ilustrovat na tˇr´ıdˇe Souradnice. Deklarujeme referenˇcn´ı promˇennou typu Souradnice Souradnice sour; V dalˇs´ım kroku vytvoˇr´ıme nov´ y objekt a inicializujeme j´ım referenˇcn´ı promˇennou. sour=new Souradnice(); Oba ˇr´ adky bychom mohli spojit do jednoho. Souradnice sour=new Souradnice(); Odkaz sour od tohoto okamˇziku ukazuje na vytvoˇren´ y objekt. Takto vytvoˇren´ y objekt m´ a dvˇe promˇenn´e instance: delka, uhel a dvˇe metody instance: x(), y(). Tento stav lze zobecnit, ˇr´ık´ ame ˇze kaˇzd´ y vytvoˇren´ y objekt m´a k dispozici vlastn´ı sadu komponent. Tyto sady komponent jsou vz´ ajemnˇe nez´ avisl´e.
5.3.2
Pˇ r´ıstup k datov´ ym poloˇ zk´ am
K datov´ ym poloˇzk´ am objektu lze pˇristupovat prostˇrednictv´ım tzv. teˇckov´e notace. Obecnˇe ji lze zapsat ve tvaru objekt.polozka Vˇsimnˇeme si, ˇze v Javˇe neexistuje jako v C++ oper´ ator nepˇr´ım´eho pˇr´ıstupu ->. Pˇr´ıstup prostˇrednictv´ım teˇckov´e notace je tedy jedin´y moˇzn´y. V naˇsem pˇr´ıpadˇe bychom k datov´ ym poloˇzk´ am mohli pˇristupovat takto: sour.delka; sour.uhel; S vyuˇzit´ım t´eto konstrukce je moˇzno datov´e poloˇzky i inicializovat. sour.delka=10; sour.uhel=20;
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR T´ımto zp˚ usobem jsme vlastnˇe provedli explicitn´ı inicializaci promˇenn´ ych. Implicitn´ı inicializace byla provedena pˇri vytvoˇren´ı objektu. Jelikoˇz se jednalo o datov´e poloˇzky, byly inicializov´ any na hodnotu 0. Vzhledem k tomu, ˇze datov´e poloˇzky byly deklarov´ any jako soukrom´e, m˚ uˇzeme k n´ım t´ımto zp˚ usobem pˇristupovat pouze z vnitˇrku tˇr´ıdy. V´ yˇse uveden´ y k´ od zapiˇsme do metody main(), kter´ a bude vypadat napˇr. takto: public static void main (String [] args) { Souradnice sour=new Souradnice(); sour.delka=10; sour.uhel=20; } Tento k´ od m˚ uˇzeme zapsat i do jin´e metody neˇz main(), metodu je pak nutn´e volat pˇri inicializaci datov´ ych poloˇzek tˇr´ıdy. Upozorˇ nujeme, ˇze tento postup inicializace nen´ı typick´ y. Nen´ı nav´ıc pˇr´ıliˇs pohodln´ y ani pˇrehledn´ y. Java pro tyto u ´ˇcely pouˇz´ıv´ a speci´ aln´ı metodu zvanou konstruktor. Pr´ ace s metodami instance S metodami instance se pracuje podobn´ ym zp˚ usobem jako s datov´ ymi poloˇzkami, opˇet vyuˇz´ıv´ ame teˇckovou notaci. Syntaxe vypad´ a takto: objekt.metoda Metody deklarovan´e ve tˇr´ıdˇe Souradnice jsou bezparametrick´e. Chceme -li urˇcit hodnotu pravo´ uhl´ ych souˇradnic pro aktu´ aln´ı hodnoty pol´ arn´ıch souˇradnic, vytvoˇr´ıme nejprve dvˇe lok´ aln´ı promˇenn´e typu double double xpr; double ypr; do kter´ ych n´ aslednˇe uloˇz´ıme spoˇcten´e hodnoty obou souˇradnic x,y. xpr=sour.x(); ypr=sour.y(); K´od opˇet zap´ıˇseme do metody main(), i kdyˇz ani zde to nen´ı podm´ınkou. V´ ysledn´e hodnoty m˚ uˇzeme vytisknout. public static void main (String [] args) { Souradnice sour=new Souradnice();//vytvoreni instance sour.delka=10; //icializace jejich datovych polozek sour.uhel=20; double xpr; //vytvoreni lokalnich promennych double ypr; xpr=sour.x();//vypocet hodnot pravouhlych souradnic ypr=sour.y(); System.out.println("X="+xpr+" Y="+ypr); }
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR
5.3.3
Ruˇ sen´ı objekt˚ u
Pˇripomeˇ nme, ˇze v jazyce Java nen´ı nutno objekty ruˇsit manu´ alnˇe. O objekty, na kter´e jiˇz neexistuje platn´ y odkaz, se postar´ a garbage collector, kter´ y je smaˇze. Odkaz na objekt m˚ uˇze zaniknout dvˇema zp˚ usoby: • Z´ anikem platnosti odkazu Odkaz se chov´ a stejnˇe jako jak´ akoliv jin´ a promˇenn´ a. Po ukonˇcen´ı bloku, ve kter´em byl deklarov´an, zanik´ a. public static void main (String [] args) { { Souradnice sour=new Souradnice(); } //zanika odkaz na objekt sour } • Pˇriˇrazen´ım hodnoty null. Hodnota null pˇredstavuje speci´ aln´ı hodnotu, jej´ıˇz pˇriˇrazen´ım doc´ıl´ıme stavu, kdy odkaz nikam neukazuje. T´ımto zp˚ usobem ho ”vynulujeme” a dos´ ahneme stejn´eho v´ ysledku jako v pˇredchoz´ım pˇr´ıpadˇe. public static void main (String [] args) { Souradnice sour=new Souradnice(); sour=null; //zanika odkaz na objekt sour } Druh´ a varianta se pouˇz´ıv´ a ˇcasto v pˇr´ıpadech, kdy pracujeme s rozs´ ahl´ ymi daty a potˇrebujeme rychle uvolnit syst´emov´e prostˇredky. Garbage collector provede n´ aslednˇe smaz´ an´ı takov´eho objektu. Neprovede ho okamˇzitˇe, ale aˇz v pˇr´ıpadˇe, kdy to s´ am uzn´ a za vhodn´e. Zopakujme, ˇze garbage collector je moˇzn´e spustit na vyˇz´ad´an´ı a s vysokou prioritou metodou System.gc().
5.3.4
Konstruktor
V pˇredchoz´ım k´ odu jsme pouˇzili ponˇekud nepohodln´ y zp˚ usob ve tvaru objekt.polozka, kter´ y jsme n´ aslednˇe i zkritizovali. Tuto konstrukci by v nˇekter´ ych pˇr´ıpadech nebylo moˇzno pouˇz´ıt, k datov´ ym poloˇzk´ am deklarovan´ ych jako priv´ atn´ı bychom se nedostali z vnˇejˇsku tˇr´ıdy. Popsan´ y zp˚ usob tedy nem˚ uˇzeme vyuˇz´ıt pro inicializaci ˇ sen´ı datov´ ych poloˇzek prov´ adˇenou z jin´e tˇr´ıdy, coˇz vˇsak pˇredstavuje pomˇernˇe ˇcast´ y zp˚ usob pr´ ace s objekty. Reˇ toho zd´ anlivˇe neˇreˇsiteln´eho probl´emu nab´ız´ı konstruktor. Konstruktor pˇredstavuje speci´ aln´ı metodu pouˇz´ıvanou pˇri inicializaci datov´ ych poloˇzek. Konstruktor je vol´an v okamˇziku vytvoˇren´ı objektu. Souradnice sour; sour=new Souradnice(); //ted je volan konstruktor Konstruktor m´ a n´ asleduj´ıc´ı vlastnosti: • Jm´eno konstruktoru je shodn´e se jm´enem tˇr´ıdy. • Konstruktor nem´ a ˇz´ adnou n´ avratovou hodnotu, ani void. Nesm´ı obsahovat kl´ıˇcov´e slovo return. • Konstruktor m˚ uˇze m´ıt parametry (explicitn´ı konstruktor) nebo nemus´ı (implicitn´ı konstruktor). • Konstruktor m˚ uˇze b´ yt pˇret´ıˇzen.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR Implicitn´ı konstruktor Implicitn´ı konstruktor je konstruktor bezparametrick´ y. Pokud nevytvoˇr´ıme konstruktor vlastn´ı, je automaticky generov´an pr´ avˇe implicitn´ı konstruktor. Ten umoˇzn ˇ uje prov´est inicializaci datov´ ych poloˇzek na v´ ychoz´ı hodnoty. V naˇsem pˇr´ıpadˇe by byly promˇenn´e delka, uhel inicializov´ any na hodnoty 0. Pokud bychom chtˇeli v r´ amci implicitn´ıho konstruktoru inicializovat promˇenn´e na jin´e neˇz v´ ychoz´ı hodnoty, museli bychom si konstruktor napsat sami. N´ asleduj´ıc´ı konstruktor provede inicializaci datov´ ych poloˇzek tˇr´ıdy na hodnoty 10 (d´elka) a 20 (´ uhel). Souradnice() { delka=10; uhel=20; } Pokud budeme vytv´ aˇret nov´e instance tˇr´ıdy souˇradnice podle implicitn´ıho konstruktoru, vˇsechny datov´e poloˇzky objekt˚ u budou inicializov´ any na stejn´e hodnoty. Podobn´eho v´ ysledku bychom mohli dos´ ahnout, pokud bychom upravili deklaraci tˇr´ıdy, a obˇe promˇenn´e inicializovali zde. public class Souradnice { private double delka=10; private double uhel=20; ... } Explicitn´ı konstruktor Explicitn´ı konstruktor je konstruktor parametrick´ y, disponuje form´ aln´ımi parametry. Umoˇzn ˇuje datov´ ym sloˇzk´ am pˇri inicializaci pˇriˇradit libovolnou hodnotu. Explicitn´ı konstruktor je vol´ an s hodnotami parametr˚ u, kter´e budou pˇriˇrazeny form´ aln´ım parametr˚ um. Pˇri inicializaci za pouˇzit´ı explicitn´ıho konstruktoru m˚ uˇze b´ yt kaˇzd´ y z objekt˚ u inicKonstruktor tedy umoˇzn ˇ uje prov´ adˇet inicializaci objektu pˇri jeho vytvoˇren´ı.ializov´an jinak, coˇz pˇri pouˇzit´ı implicitn´ıho konstruktoru nen´ı moˇzn´e. Pod´ıvejme na inicializaxi s vyuˇzit´ıme explicitn´ıho konstruktoru: Souradnice (double d, double u) { delka=d; uhel=u; } Chceme -li vytvoˇrit nov´ y objekt a inicializovat ho explicitn´ım konstruktorem, m˚ uˇzeme postupovat takto: Souradnice sour; sour=new Souradnice(10, 20); //volan explicitni konstruktor S vyuˇzit´ım odkazu this lze explicitn´ı konstruktor pˇrepsat do tvaru, ve kter´em maj´ı promˇenn´e instance stejn´e jm´eno jako form´ aln´ı parametry.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR Souradnice (double delka, double uhel) { this.delka=delka; this.uhel=uhel; } Odkaz this tedy umoˇzn´ı rozliˇsit obˇe promˇenn´e tak, ˇze nedojde ke konfliktu jejich identifik´ ator˚ u. Na pˇr´ıpadech implicitn´ıho a explicitn´ıho konstruktoru je patrn´e, ˇze konstruktory mohou b´ yt pˇretˇeˇzov´ any. Pˇretˇeˇzov´an´ı explicitn´ıch konstruktor˚ u se ˇr´ıd´ı stejn´ ymi z´ akonitostmi jako pˇretˇeˇzov´ an´ı ostatn´ıch metod, nezapomeˇ nme, ˇze i konstruktor je ”pouze” metodou.
5.3.5
Odkaz this
Existuje speci´ aln´ı typ odkazu, kter´ y m´ a kaˇzd´ a z metod. Odkaz this ukazuje na objekt, se kter´ ym byla metoda vol´ ana. Tento odkaz je ”skryt´ y”, nen´ı potˇreba ho nˇekde inicializovat. Zaruˇcuje, ˇze kaˇzd´ a metoda pracuje s daty sv´eho objektu. S odkazem this pracujeme tak´e prostˇrednictv´ım teˇckov´e notace. Pro bliˇzˇs´ı pochopen´ı lze v´ yˇse uveden´ y implicitn´ı konstruktor zapsat prostˇrednictv´ım this. Souradnice() { this.delka=10; this.uhel=20; }
5.3.6
Inicializace objektu jin´ ym objektem
Odkaz this je moˇzno pouˇz´ıt i pˇri inicializaci jednoho objektu objektem jin´ ym za pouˇzit´ı explicitn´ıho konstruktoru. Na rozd´ıl od C++ nen´ı nutno v takov´em pˇr´ıpadˇe vytv´ aˇret kop´ırovac´ı konstruktor. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad, ve kter´em definujeme explicitn´ı konstruktor ve tvaru Souradnice (Souradnice s) { this.delka=s.delka; this.uhel=s.uhel; } Takov´ y explicitn´ı konstruktor m´ a jako form´ aln´ı parametr odkaz na jin´ y objekt tˇr´ıdy. Chceme -li vytvoˇrit objekt tak, aby byl pˇri sv´em vzniku inicializov´ an jin´ ym objektem, budeme odkaz na tento objekt pˇred´avat jako parametr explicitn´ımu konstruktoru. Souradnice sour=new Souradnice(10, 20); //explicitni inicializace objektu sour2 objektem sour Souradnice sour2=new Souradnice(sour); Tento postup je v OOP velmi ˇcasto pouˇz´ıv´ an, s jeho pomoc´ı m˚ uˇzeme vytv´ aˇret pomˇernˇe snadno kopie objekt˚ u. ˇ aˇr by se s n´ım mˇel proto nejen sezn´ Cten´ amit, ale mˇel by se ho nauˇcit i pouˇz´ıvat.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR
5.3.7
Spuˇ stˇ en´ı metody v konstruktoru.
V tˇele konstruktoru lze volat i metody. Tento pˇr´ıstup se pouˇz´ıv´ a v pˇr´ıpadˇe, kdy je nutno prov´est ”sloˇzitˇejˇs´ı” inicializaci datov´ ych poloˇzek (napˇr. tak, ˇze hodnoty jsou jim nastaveny nˇejak´ ym funkˇcn´ım pˇredpisem). Pod´ıvejme se na n´ asleduj´ıc´ı, byt’ ponˇekud umˇel´ y pˇr´ıpad. Souradnice (double d, double u) { NastavParametry (d,u); } void NastavParametry(double d, double u) { this.delka=d; this.uhel=u; } Objekt n´ aslednˇe inicializujeme stejn´ ym zp˚ usobem Souradnice sour=new Souradnice(10, 20);
5.3.8
Pr´ ace se statick´ ymi ˇ cleny tˇ r´ıdy
Mezi statick´e ˇcleny tˇr´ıdy patˇr´ı statick´e promˇenn´e a statick´e metody. Statick´e promˇenn´e naz´ yv´ ame promˇenn´e tˇr´ıdy, budou spoleˇcn´e vˇsem instanc´ım tˇr´ıdy. Statick´e metody jsou takov´e metody, se kter´ ymi m˚ uˇzeme pracovat, aniˇz je vytvoˇrena nˇejak´ a instance tˇr´ıdy. Statick´e datov´e poloˇzky tˇr´ıdy jsou deklarov´ any s kl´ıˇcov´ ym slovem static. Promˇ enn´ e tˇ r´ıdy Nejprve se sezn´ am´ıme se statick´ ymi promˇenn´ ymi a jejich vyuˇzit´ım. Statick´e promˇenn´e se velmi ˇcasto pouˇz´ıvaj´ı jako tzv. poˇcitadla instanc´ı. Pomoc´ı nich m˚ uˇzeme zjistit, kolik objekt˚ u dan´e tˇr´ıdy jiˇz bylo vytvoˇreno. Pokud je souˇc´ ast´ı tˇr´ıdy statick´ a promˇenn´ a, m˚ uˇzeme na vhodn´em m´ıstˇe, napˇr. v konstruktoru, prov´ adˇet jej´ı inkrementaci. Ke statick´ ym promˇenn´ ym pˇristupujeme konstrukc´ı trida.promenna; Vˇsimnˇeme si toho rozd´ılu, k promˇenn´ ym instance pˇristupujeme prostˇrednictv´ım odkazu this. Statick´e promˇenn´e jsou inicializov´ any pouze 1x, a to pˇri sv´em vytvoˇren´ı. Upravme deklaraci naˇs´ı tˇr´ıdy do tvaru: public class Souradnice { private double delka; private double uhel; private static int pocet; ... }
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR V deklaraci tˇr´ıdy pˇribyla statick´ a promˇenn´ a pocet, kter´ a je pˇri vytvoˇren´ı prvn´ı instance inicializov´ana na v´ ychoz´ı hodnotu, tj. 0. Bude nutno upravit i konstruktor (resp. vˇsechny konstruktory), ve kter´em by mˇela b´ yt statick´ a promˇenn´ a pˇri vytvoˇren´ı kaˇzd´e nov´e instance inkrementov´ ana o hodnotu 1. Souradnice (double delka, double uhel) { this.delka=delka; this.uhel=uhel; Souradnice.pocet++; } Pˇri kaˇzd´em vytvoˇren´ı nov´eho objektu za pouˇzit´ı explicitn´ıho konstruktoru Souradnice sour1=new Souradnice(10, 20); Souradnice sour2=new Souradnice(10, 20); Souradnice sour3=new Souradnice(10, 20); se zv´ yˇs´ı hodnota statick´e promˇenn´e pocet o 1. Metody tˇ r´ıdy Metody tˇr´ıdy (tj. statick´e metody) mohou pouˇz´ıvat pouze lok´ aln´ı nebo statick´e promˇenn´e. S t´ımto faktem jsme se jiˇz sezn´ amili v u ´vodu kapitoly. Pˇresto se statick´e metody pouˇz´ıvaj´ı v OOP pomˇernˇe ˇcasto. Jsou dva typick´e pˇr´ıklady pouˇzit´ı. • Prvn´ı pˇredstavuj´ı metody tˇr´ıdy Math, kter´e jsou deklarov´ any jako statick´e. S t´ımto pˇr´ıstupem jsme se v praxi jiˇz nˇekolikr´ at setkali, uv´ ad´ıme ho tedy pouze pro u ´plnost. • Druhou moˇznost´ı pouˇzit´ı statick´ ych metod je spolupr´ ace se statick´ ymi promˇenn´ ymi. Ty jsou stejnˇe jako jin´e promˇenn´e deklarov´ any zpravidla jako priv´ atn´ı. Pro pˇr´ıstup k nim je tedy nutno pouˇz´ıt statickou metodu. Pomoc´ı metod tˇr´ıdy tedy m˚ uˇzeme mˇenit nebo z´ısk´ avat hodnoty promˇenn´ ych tˇr´ıdy. Ke statick´ ym metod´ am pˇristupujeme ve tvaru trida.metoda; Pokud ke statick´e tˇr´ıdˇe pˇristupujeme z tˇr´ıdy, ve kter´e je deklarov´ ana, m˚ uˇzeme n´ azev tˇr´ıdy vynechat. Pr´aci s metodami tˇr´ıdy budeme ilustrovat na n´ asleduj´ıc´ım pˇr´ıkladu: do tˇr´ıdy Souradnice pridejme statickou metodu, kter´ a bude vracet poˇcet vytvoˇren´ ych objekt˚ u public static int Pocet() {return pocet;} Budeme -li pomoc´ı t´eto statick´e metody vr´ atit poˇcet instanc´ı, m˚ uˇzeme to prov´est napˇr. takto. public static void main (String [] args) { //Vytvoreni instanci Souradnice sour1=new Souradnice(10, 20); Souradnice sour2=new Souradnice(10, 20); Souradnice sour3=new Souradnice(10, 20); //Spocitani instanci int kolik=Souradnice.Pocet(); System.out.println ("Celkem objektu:"+kolik); }
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR
5.3.9
Gettery a settery
Dodrˇzujeme -li princip zapouzdˇren´ı, k datov´ ym poloˇzk´ am tˇr´ıdy (deklarovan´ ym jako private) m˚ uˇzeme pˇristupovat a manipulovat s nimi pouze prostˇrednictv´ım metod. V Javˇe jsou standardizov´ any n´ azvy pro urˇcit´e typy metod: • Pro nastaven´ı hodnot datov´ ych poloˇzek jsou pouˇz´ıv´ any tzv. settery, tj. metody maj´ıc´ı ve sv´em n´azvu slovo ”set”. V pˇr´ıpadˇe vzorov´e tˇr´ıdy m˚ uˇzeme pro nastaven´ı hodnot datov´ ych poloˇzek delka/uhel vytvoˇrit metody: public void setDelka(double d) { this.delka=d; } public void setUhel(double u) { this.uhel=u; } • Pro z´ısk´ av´ an´ı hodnot datov´ ych poloˇzek b´ yvaj´ı pouˇz´ıv´ any tzv. gettery, tj. metody maj´ıc´ı ve sv´em n´azvu slovo ”get”. V pˇr´ıpadˇe vzorov´e tˇr´ıdy m˚ uˇzeme pro z´ısk´ an´ı hodnot datov´ ych poloˇzek delka/uhel vytvoˇrit metody: public double getDelka() {return this.delka;} public double getUhel() {return this.uhel;} Nic n´ am nebr´ an´ı, metody pro nastaven´ı a z´ısk´ an´ı hodnot pojmenovat jinak, nicm´enˇe v´ yˇse uveden´ y zp˚ usob ˇ je v Javˇe velmi ˇcasto pouˇz´ıv´ an. Rada v´ yvojov´ ych prostˇred´ı um´ı automaticky generovat pro datov´e poloˇzky gettery a settery.
5.3.10
Pole objekt˚ u
Pracujeme -li s vˇetˇs´ım mnoˇzstv´ım instanc´ı jedn´e tˇr´ıdy, je vhodn´e ukl´ adat je do pole. Pr´ ace s polem objekt˚ u je podobn´ a jako pr´ ace s polem primitivn´ıch datov´ ych typ˚ u. Nestaˇc´ı vˇsak vytvoˇrit pouze pole, mus´ıme prov´est i druh´ y krok, a t´ım je vytvoˇren´ı instanc´ı jednotliv´ ych objekt˚ u prostˇrednictv´ım oper´ atoru new. K jednotliv´ ym objekt˚ um lze n´ aslednˇe pˇristupovat prostˇrednictv´ım indexu. Postup budeme ilustrovat na praktick´em pˇr´ıpadˇe tˇr´ıdy Souradnice. Budeme vytv´ aˇret pole 10 objekt˚ u. V prvn´ım kroku deklarujeme odkaz ukazuj´ıc´ı na pole objekt˚ u. Souradnice [] pole; N´ aslednˇe vytvoˇr´ıme pole pole odkaz˚ u na objekty, kter´ ym inicializujeme odkaz: pole=new Souradnice[10]; V tomto okamˇziku vˇsak jednotliv´e prvky pole neukazuj´ı na ˇz´ adn´e konkr´etn´ı objekty, jejich hodnota je null. Teprve nyn´ı vytvoˇr´ıme jednotliv´e objekty, odkazy na nˇe inicializujeme poloˇzky pole. Inicializace promˇenn´ ych instance m˚ uˇze probˇehnout jak prostˇrednictv´ım implicitn´ıho, tak prostˇrednictv´ım explicitn´ıho konstruktoru; v naˇsem pˇr´ıpadˇe probˇehne inicializace prostˇrednictv´ım explicitn´ıho konstruktoru.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR for (int i=0;i<pole.length;i++) { pole[i]=new Souradnice(10,20); } S jednotliv´ ymi objekty m˚ uˇzeme pracovat prostˇrednictv´ım odkaz˚ u, Jednotliv´e hodnoty souˇradnic x, y m˚ uˇzeme napˇr. vypsat za pouˇzit´ı cyklu. for (int i=0;i<pole.length;i++) { System.out.println("X="+pole[i].x()+"Y="+pole[i].y()); pole[i]=new Souradnice(10,20); }
5.3.11
Pˇ red´ av´ an´ı objekt˚ u jako parametr˚ u
Objekty jsou na rozd´ıl od primitivn´ıch datov´ ych typ˚ u v Javˇe pˇred´ av´ any odkazem. Pro pˇripomenut´ı uved’me, ˇze se tento pˇr´ıstup t´ yk´ a i pr´ ace s poli. Princip pˇ red´ av´ an´ı objekt˚ u. Form´ aln´ım parametrem v metodˇe je odkaz na objekt tˇr´ıdy, tj. reference. Skuteˇcn´ y parametr pˇredstavuje odkaz na jiˇz existuj´ıc´ı objekt. Oba odkazy by mˇely b´ yt stejn´eho datov´eho typu, v opaˇcn´em pˇr´ıpadˇe je provedena implicitn´ı konverze (pokud je to moˇzn´e). Prostˇrednictv´ım reference m˚ uˇze metoda pˇristupovat k metod´ am volaj´ıc´ıho objektu (popˇr. k datov´ ym poloˇzk´ am, nejsou -li deklarov´ any jako priv´ atn´ı). T´ımto zp˚ usobem m˚ uˇzeme prostˇrednictv´ım form´ aln´ıho parametru mˇenit hodnoty skuteˇcn´eho parametru, tj. “volaj´ıc´ı” data. Tento pˇr´ıstup ilustrujeme na nov´e tˇr´ıdˇe Prevod, kterou vytvoˇr´ıme. Bude v n´ı implementov´ ana i metoda vzdalenost(), kter´ a zpˇetnˇe z pravo´ uhl´ ych souˇradnic spoˇcte jednu z pol´ arn´ıch souˇradnic: vzd´ alenost. public class Prevod { public double vzdalenost (Souradnice objekt) { return Math.sqrt(objekt.x*objekt.x+objekt.y*objekt.y)); } } Metoda m´ a jako form´ aln´ı parametr odkaz na objekt tˇr´ıdy Souradnice. Prostˇrednictv´ım form´ aln´ıho parametru pˇristupuje k metod´ am x() a y() volaj´ıc´ıho objektu. V metodˇe main() tˇr´ıdy Souradnice vytvoˇr´ıme dva objekty. public static void main (String [] args) { //Vytvoreni instanci Souradnice sour=new Souradnice(10, 20); Prevod prev=new Prevod(); //Volani metody a predani odkazu na objekt System.out.println("Vzdalenost="+prev.vzdalenost(sour)); } Metodˇe vzdalenost() pˇred´ ame odkaz na objekt sour, spoˇctenou vzd´ alenost n´ aslednˇe vytiskneme.
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR Pr´ ace s maticemi. Pr´ aci s poli ilustrujme na jednoduch´em pˇr´ıkladu maticov´ ych v´ ypoˇct˚ u. Implementujme tˇr´ıdu Matice, kter´ a bude matici ukl´ adat do 2D pole. Pro z´ akladn´ı operace s maticemi vytvoˇrme tˇr´ıdu Operace, kter´ a bude sˇc´ıtat dvˇe matice. Dalˇs´ı v´ ypoˇcty (transpozice, souˇcin) by bylo moˇzno realizovat obdobn´ ym zp˚ usobem, z d˚ uvodu jednoduchosti je vˇsak nebudeme uv´ adˇet. public class Matice { private double [][] pole; private int m, n; Matice (double [][] p) { this.m=p.length; this.n=p[0].length; pole=new double[m][n]; for (int i=0; i<m;i++) { for (int j=0;i
ˇ ´IDY, METODY KAPITOLA 5. OBJEKTY, TR double [][] m1={{1,2,3},{4,5,6}}; double [][] m2={{1,0,1},{1,0,1}}; double [][] m3={{0,0,0},{0,0,0}}; //vytvoreni objektu Matice A=new Matice(m1); Matice B=new Matice(m2); Matice B=new Matice(m2); Operace o=new Operace(); //Soucet matic o.Soucet(A,B,C); } Pot´e vytvoˇr´ıme objekt tˇr´ıdy Operace, jako form´ aln´ı parametry mu pˇred´ ame odkazy na objekty A, B, C. N´ aslednˇe bychom v´ yslednou matici mohli napˇr. vytisknout, do tˇr´ıdy Matice bychom mohli implementovat novou metodu realizuj´ıc´ı tuto operaci. V´ yˇse uveden´ y pˇr´ıstup je pouze ilustrativn´ı, v praxi by bylo vhodn´e zamyslet se nad efektivnˇejˇs´ım n´ avrhem tˇr´ıd a metod.
Kapitola 6
Dˇ ediˇ cnost Dˇediˇcnost je jedn´ım ze z´ akladn´ıch princip˚ u objektovˇe orientovan´eho programov´an´ı. Vyuˇz´ıv´a poznatku, ˇze nˇekter´e objekty maj´ı podobn´e vlastnosti. Pomoc´ı dˇediˇcnosti m˚ uˇzeme pˇri n´avrhu tˇr´ıd pouˇz´ıt hierarchick´ y pˇr´ıstup a vytvoˇrit strom podˇr´ızen´ ych a nadˇr´ızen´ ych tˇr´ıd. Tˇr´ıdy na niˇzˇs´ı u ´rovni mohou dˇedit vlastnosti a chov´an´ı tˇr´ıd nach´ azej´ıc´ıch se na vyˇsˇs´ı u ´rovni. Novou tˇr´ıdu lze odvodit z podobn´e existuj´ıc´ı tˇr´ıdy pˇrid´an´ım poˇzadovan´ ych funkc´ı a vlastnost´ı. Tˇr´ıdu, ze kter´e dˇed´ıme, naz´ yv´ame rodiˇcovskou nebo tak´e b´ azovou tˇr´ıdou. Zdˇedˇen´e tˇr´ıdy oznaˇcujeme jako tˇr´ıdy odvozen´e popˇr. je naz´ yv´ame potomky. Java, na rozd´ıl od jin´ ych jazyk˚ u, podporuje pouze jednoduchou dˇediˇcnost. Potomek tedy m˚ uˇze m´ıt nejv´ yˇse ˇ asteˇcnou n´ jednoho rodiˇce. C´ ahradu v´ıcen´ asobn´e dˇediˇcnosti v Javˇe pˇredstavuje rozhran´ı. Sezn´am´ıme se s n´ım v kapitole 9. Vˇsimnˇeme si, ˇze dˇediˇcnost je v jazyce Java hluboce zakoˇrenˇena. Pokud novˇe vytv´aˇrenou tˇr´ıdu explicitnˇe nedˇed´ıme z nˇejak´e jin´e tˇr´ıdy, nov´ a tˇr´ıda sv´e vlastnosti implicitnˇe dˇed´ı od b´azov´e tˇr´ıdy Object. D˚ ukazem budeme ilustrovat pˇri vytvoˇren´ı tˇr´ıdy NovaTrida, kter´a nem´a ˇz´adn´e promˇenn´e ani metody, pouze implicitn´ı konstruktor: public class NovaTrida { public NovaTrida() { } } Pokud vytvoˇr´ıme instanci tˇr´ıdy NovaTrida, budeme m´ıt k dispozici metody equals(), getClass(), hashCode(), notify(), notifyAll(), toString() a wait().
6.1
Deklarace rodiˇ covsk´ e a odvozen´ e tˇ r´ıdy
Dˇediˇcnost naznaˇcuje podobnost mezi odvozenou a rodiˇcovskou tˇr´ıdou. Fakt, ˇze je odvozen´a tˇr´ıda potomkem rodiˇcovsk´e tˇr´ıdy, uv´ ad´ıme v deklaraci odvozen´e tˇr´ıdy pˇr´ıkazem extends, za kter´ ym n´asleduje n´azev rodiˇcovsk´e tˇr´ıdy. public class OdvozenaTride extends BazovaTrida { // nejaky kod }
61
ˇ CNOST ˇ KAPITOLA 6. DEDI Odvozenou tˇr´ıdu t´ımto postupem zpravidla rozˇsiˇrujeme o novou funkˇcnost nebo upravujeme funkˇcnost, kter´a n´ am nevyhovuje. Princip dˇediˇcnosti budeme ilustrovat na praktick´em pˇr´ıkladu. Vytvoˇr´ıme tˇr´ıdou Auto, kter´ a bude obsahovat datovou poloˇzky rychlost, max_rychlost a implementovat metody zastav() a zrychli(). Odvozen´a tˇr´ıda Osobni bude obsahovat datov´e poloˇzky osob, max_osob a implementovat metody pristup() a vystup(). Deklarace rodiˇ covsk´ e tˇ r´ıdy. V souladu s v´ yˇse uveden´ ymi informacemi vytvoˇr´ıme deklaraci rodiˇcovsk´e tˇr´ıdy. Obˇe datov´e poloˇzky budou typu float, rychlost auta se mˇen´ı spojitˇe. Konstruktor tˇr´ıdy bude explicitn´ı, kaˇzd´emu nov´emu vozidlu stanov´ıme aktu´ aln´ı rychlost a maxim´ aln´ı rychlost, kterou nesm´ı pˇrekroˇcit. Metoda zastav() nastav´ı okamˇzitou rychlost rovnu nule, metoda pridej() zv´ yˇs´ı aktu´ aln´ı rychlost vozidla o zadanou hodnotu ale tak, aby nepˇres´ ahla maxim´ aln´ı rychlost. public class Auto { private float rychlost, max_rychlost; public Auto(float max_rychlost, float rychlost) { this.max_rychlost=max_rychlost; this.rychlost=rychlost; } public void zastav() { this.rychlost=0; } public void zrychli(double v) { if(this.rychlost<max_rychlost-v) { this.rychlost+=v; } else this.rychlost=max_rychlost; } }
Deklarace odvozen´ e tˇ r´ıdy. Datov´e poloˇzky odvozen´e tˇr´ıdy budou typu int, pouˇzijeme explicitn´ı konstruktor, kter´emu jako form´ aln´ı parametr pˇred´ ame poˇcet osob a maxim´ aln´ı poˇcet osob ve vozidle. Metoda vystup() nastav´ı poˇcet osob ve vozidle nule, metoda nastup() zv´ yˇs´ı poˇcet lid´ı ve vozidle o zadanou hodnotu tak, aby nepˇres´ ahl maxim´ aln´ı poˇcet pˇrepravovan´ ych osob. public class Osobni extends Auto { private int lidi, max_lidi; public Osobni(int max_lidi, int lidi) { this.max_lidi=max_lidi; this.lidi=lidi; } public void vystup()
ˇ CNOST ˇ KAPITOLA 6. DEDI { this.lidi=0; } public void pristup(int l) { if(this.lidi<max_lidi-l) { this.lidi+=l; } else this.lidi=max_lidi; } } Aˇckoliv to zat´ım na prvn´ı pohled nen´ı zˇrejm´e, implementace odvozen´e tˇr´ıdy vykazuje jeden podstatn´ y nedostatek. Pokus´ıme se vytvoˇrit instance odvozen´e a rodiˇcovsk´e tˇr´ıdy. public static void main(String[] args) { Auto a = new Auto(150,100); Osobni o=new Osobni (4,2); } Prvn´ı pˇr´ıkaz vytvoˇr´ı instanci rodiˇcovsk´e tˇr´ıdy a inicializuje jej´ı datov´e poloˇzky. Druh´ y pˇr´ıkaz vytvoˇr´ı instanci odvozen´e tˇr´ıdy, inicializuje datov´e poloˇzky odvozen´e tˇr´ıdy, ale jiˇz neinicializuje poloˇzky rodiˇcovsk´e tˇr´ıdy. Na problematiku inicializace datov´ ych poloˇzek s vyuˇzit´ım konstruktor˚ u se tedy budeme muset pod´ıvat podrobnˇeji v n´ asleduj´ıc´ı kapitole.
6.1.1
Inicializace rodiˇ covsk´ e tˇ r´ıdy
Vzhledem k tomu, ˇze pracujeme se dvˇema tˇr´ıdami, inicializace instanc´ı rodiˇcovsk´e a odvozen´e tˇr´ıdy se na prvn´ı pohled m˚ uˇze zd´ at ponˇekud nepˇrehledn´ a. Pro inicializaci datov´ ych poloˇzek rodiˇcovsk´e tˇr´ıdy pouˇz´ıv´ ame konstruktory. Mohou b´ yt pˇret´ıˇzen´e. Pouˇzijeme -li konstruktor implicitn´ı, budou m´ıt vˇsechny instance rodiˇcovsk´e tˇr´ıdy stejn´e vlastnosti. Pouˇzijeme -li konstruktor explicitn´ı, m˚ uˇze m´ıt kaˇzd´ a instance jin´e vlastnosti. V pˇr´ıpadˇe rodiˇcovsk´e tˇr´ıdy se ˇz´ adn´e pˇrekvapen´ı nekon´ a, jej´ı datov´e poloˇzky m˚ uˇzeme inicializovat stejn´ ym zp˚ usobem jako datov´e poloˇzky jak´ekoliv jin´e tˇr´ıdy.
6.1.2
Inicializace odvozen´ e tˇ r´ıdy
V pˇr´ıpadˇe inicializace datov´ ych poloˇzek odvozen´e tˇr´ıdy je situace sloˇzitˇejˇs´ı. Inicializaci datov´ ych poloˇzek instance odvozen´e tˇr´ıdy mus´ı pˇredch´ azet inicializace datov´ ych poloˇzek rodiˇcovsk´e tˇr´ıdy. Vlastnosti instance odvozen´ı tˇr´ıdy mohou b´ yt z´ avisl´e na vlastnostech instance rodiˇcovsk´e tˇr´ıdy. Vytv´ aˇr´ıme –li instanci odvozen´e tˇr´ıdy, je nejprve vyvol´ an konstruktor z´ akladn´ı tˇr´ıdy a teprve potom konstruktor odvozen´e tˇr´ıdy. Mus´ı b´ yt vytvoˇren jako prvn´ı, protoˇze konstruktor odvozen´e tˇr´ıdy m˚ uˇze vych´azet z poloˇzek z´akladn´ı tˇr´ıdy. Konstruktor rodiˇcovsk´e tˇr´ıdy je proveden pˇred t´ım, neˇz program vstoup´ı do konstruktoru odvozen´e tˇr´ıdy. Instance odvozen´e tˇr´ıdy nem˚ uˇze b´ yt vytvoˇrena dˇr´ıve, neˇz je vytvoˇrena instance z´ akladn´ı tˇr´ıdy. Konstruktor nadˇrazen´e tˇr´ıdy mus´ıme volat pomoc´ı kl´ıˇcov´eho slova super() se seznamem form´ aln´ıch parametr˚ u. Pokud tak neuˇcin´ıme, je vol´ an automaticky konstruktor implicitn´ı konstruktor rodiˇcovsk´e tˇr´ıdy.
ˇ CNOST ˇ KAPITOLA 6. DEDI Pokud rodiˇcovsk´ a tˇr´ıda obsahuje pouze implicitn´ı konstruktor, nemus´ıme v odvozen´e tˇr´ıdˇe tento konstruktor explicitnˇe volat. Teprve po vykon´ an´ı konstruktoru rodiˇcovsk´e tˇr´ıdy sm´ıme prov´est inicializaci datov´ ych poloˇzek rodiˇcovsk´e tˇr´ıdy. Tu prov´ ad´ıme standardn´ım zp˚ usobem. Upraven´ y pˇr´ıklad konstruktoru odvozen´e tˇr´ıdy bude vypadat takto: public Osobni(float max_rychlost, float rychlost, int max_lidi, int lidi) { super(max_rychlost, rychlost); this.max_lidi=max_lidi; this.lidi=lidi; } Chceme -li vytvoˇrit instanci odvozen´e tˇr´ıdy, postupujeme takto: Osobni o=new Osobni (150,100, 4,2); V tomto pˇr´ıpadˇe jiˇz inicializace datov´ ych poloˇzek rodiˇcovsk´e tˇr´ıdy pˇri vytv´ aˇren´ı instance odvozen´e tˇr´ıdy probˇehne korektnˇe. Plat´ı tedy, ˇze odvozen´ a tˇr´ıda zdˇed´ı po rodiˇcovsk´e tˇr´ıdˇe vˇsechny jej´ı datov´e poloˇzky a vˇsechny metody s v´ yjimkou konstruktoru. Metody rodiˇcovsk´e a odvozen´e tˇr´ıdy pro jednotliv´e instance vol´ ame a.zastav(); a.pridej(25); o.vystup(); o.pristup(2);
6.2
Pˇ redefinov´ an´ı a pˇ ret´ıˇ zen´ı metody
Ve vˇetˇsinˇe pˇr´ıpad˚ u, kdy doplˇ nujeme metody odvozen´e tˇr´ıdy o novou funkˇcnost, prov´ ad´ıme jejich pˇredefinov´ av´ an´ı. Pˇripomeˇ nme rozd´ıl mezi pˇredefinov´ an´ım a pˇret´ıˇzen´ım metody. Pˇredefinovan´a metoda mus´ı m´ıt stejnou hlaviˇcku, tj. jm´eno i seznam form´ aln´ıch parametr˚ u. Pokud by bylo pouˇzito stejn´e jm´eno, ale jin´ y poˇcet form´ aln´ıch parametr˚ u ˇci jin´ y typ form´ aln´ıch parametr˚ u, doˇslo by pouze k pˇret´ıˇzen´ı metody. V odvozen´e tˇr´ıdˇe m˚ uˇzeme pˇredefinovat metody zastav() a zrychli() tak, aby vypisovaly aktu´ aln´ı rychlost. public void zastav() { this.rychlost=0; System.out.println(this.rychlost); } public void zrychli(double v) { if(this.rychlost<max_rychlost-v)
ˇ CNOST ˇ KAPITOLA 6. DEDI { this.rychlost+=v; } else this.rychlost=max_rychlost; System.out.println(rychlost); } Vytvoˇr´ıme pˇret´ıˇzenou metodu zrychli(), jej´ımˇz vykon´ an´ım se zv´ yˇs´ı rychlost o 10 km/hod. public void zrychli() { if(this.rychlost<max_rychlost-10) { this.rychlost+=10; } else this.rychlost=max_rychlost; System.out.println(rychlost); } Pˇret´ıˇzenou metodu vol´ ame ve tvaru a.zrychli();
6.3
Fin´ aln´ı metody a fin´ aln´ı tˇ r´ıdy
Fin´ aln´ı metody pˇredstavuj´ı takov´e metody, kter´e nemohou b´ yt v odvozen´e tˇr´ıdˇe pˇredefinov´ any. Takov´a metoda nem˚ uˇze b´ yt pˇrekryta, pouze pˇret´ıˇzena. Fin´ aln´ı metody jsou oznaˇceny v rodiˇcovsk´e tˇr´ıdˇe kl´ıˇcov´ ym slovem final. Pouˇz´ıvaj´ı se ve speci´ aln´ıch pˇr´ıpadech, napˇr. z d˚ uvodu zaruˇcen´ı stejn´e funkˇcnosti metody i v odvozen´e tˇr´ıdˇe. Typick´ ym pˇr´ıkladem m˚ uˇze b´ yt metoda zastav(), kter´ a jak´emukoliv potomkovi tˇr´ıdy Auto nastav´ı nulovou rychlost, d˚ usledek zastaven´ı je u vˇsech aut stejn´ y, maj´ı nulovou rychlost. final void zastav() { this.rychlost=0; System.out.println(this.rychlost); }
Fin´ aln´ı tˇr´ıdy pˇredstavuj´ı takov´e tˇr´ıdy, kter´e nen´ı moˇzn´e zdˇedit. B´ yvaj´ı naz´ yv´ any koncov´ymi tˇr´ıdami. Tˇr´ıdy oznaˇcen´e jako final mohou b´ yt pˇri pˇrekladu optimalizov´ any vzhledem k rychlosti. Uk´ azka fin´ aln´ı tˇr´ıdy. final class Auto { private float rychlost, max_rychlost; public Auto(float max_rychlost, float rychlost) { this.max_rychlost=max_rychlost; this.rychlost=rychlost;
ˇ CNOST ˇ KAPITOLA 6. DEDI } final void zastav() { this.rychlost=0; System.out.println(this.rychlost); } public void zrychli(double v) { if(this.rychlost<max_rychlost-v) { this.rychlost+=v; } else this.rychlost=max_rychlost; } }
Fin´ aln´ı tˇr´ıda m˚ uˇze obsahovat jak metody fin´ aln´ı, tak i nefin´ aln´ı.
6.4
Abstraktn´ı metody a abstraktn´ı tˇ r´ıdy
Abstraktn´ı metody jsou takov´e metody, kter´e mus´ı b´ yt v odvozen´e tˇr´ıdˇe pˇredefinov´ any. Pokud v rodiˇcovsk´e tˇr´ıdˇe deklarujeme metodu jako abstraktn´ı, vynucujeme jej´ı pˇredefinov´ an´ı v odvozen´e tˇr´ıdˇe. Neprovedeme -li v odvozen´e tˇr´ıdˇe pˇredefinov´ an´ı takov´e metody, program nebude pˇreloˇzen. Abstraktn´ı metody jsou tedy protikladem fin´ aln´ıch metod. Jestliˇze je v rodiˇcovsk´e tˇr´ıdˇe um´ıstˇena alespoˇ n jedna abstraktn´ı metoda, mus´ı b´ yt i rodiˇcovsk´ a tˇr´ıda deklarov´ ana jako abstraktn´ı. Od abstraktn´ı tˇr´ıdy tedy nen´ı moˇzn´e vytvoˇrit instanci. Jedinou moˇznost´ı manipulace s takovou tˇr´ıdou je jej´ı kompletn´ı pˇredefinov´ an´ı v odvozen´e tˇr´ıdˇe.1 Abstraktn´ı tˇr´ıdy se ˇcasto pouˇz´ıvaj´ı pˇri tvorbˇe ˇsablon, podle kter´ ych budou vytv´ aˇreny odvozen´e tˇr´ıdy. V odvozen´ ych tˇr´ıd´ ach se pak budou navrˇzen´e metody implementovat. Konkr´etnˇe ˇreˇceno: pokud v´ıme, ˇze metoda bude muset b´ yt v kaˇzd´e odvozen´e tˇr´ıdˇe navrˇzena jinak, implementujeme ji jako abstraktn´ı. Princip pr´ ace s abstraktn´ı tˇr´ıdy uk´ aˇzeme na pˇr´ıkladu. Vytvoˇr´ıme abstraktn´ı metodu s n´ azvem srot(), kter´a bude signalizovat, ˇze auto jiˇz patˇr´ı do ˇsrotu. Z´ akladn´ım krit´eriem bude poˇcet odjezdˇen´ ych kilometr˚ u. Jin´a krit´eria budou pro auta osobn´ı, n´ akladn´ı, sportovn´ı, atd. abstract class Auto { ... abstract bool srot(float km){} } V odvozen´ ych tˇr´ıd´ ach je nutno metodu srot() pˇredefinovat. Ve tˇr´ıdˇe Osobni m˚ uˇze vypadat takto. public class Osobni extends Auto { 1 Abstraktn´ ı metody proto neobsahuj´ı ˇ z´ adn´ y v´ ykonn´ y k´ od. Nemˇ elo by cenu ho uv´ adˇ et, protoˇ ze metoda bude stejnˇ e pˇredefinov´ ana.
ˇ CNOST ˇ KAPITOLA 6. DEDI ... abstract bool srot(float km){} { if (km>200000) return true; else return false; }
6.5
Konverze mezi instancemi rodiˇ covsk´ e a odvozen´ e tˇ r´ıdy
Pˇri operac´ıch s tˇr´ıdami tvoˇr´ıc´ıch dˇedickou posloupnost m˚ uˇzeme prov´ adˇet konverzi mezi instancemi rodiˇcovsk´e a odvozen´e tˇr´ıdy. Vytvoˇr´ıme -li instanci rodiˇcovsk´e a odvozen´e tˇr´ıdy, plat´ı: • potomek na pˇredka m˚ uˇze b´ yt pˇretypov´ an implicitnˇe. • pˇredek na potomka mus´ı b´ yt pˇretypov´ an explicitnˇe. Pˇretypov´ an´ı pˇredka na potomka naz´ yv´ ame pˇretypov´ an´ım nahoru, pˇretypov´ an´ı na pˇredka pˇretypov´ an´ım dol˚ u. Pˇretypov´an´ı smˇerem nahoru pˇredstavuje pˇretypov´ an´ı konkr´etnˇejˇs´ıho datov´eho typu na obecnˇejˇs´ı. Pˇretypov´an´ı smˇerem dol˚ u pak pˇretypov´ an´ı z obecnˇejˇs´ıho datov´eho typu na konkr´etnˇejˇs´ı. Auto a = new Auto(); Osobni o = new Osobni(); a=o; o=(Osobn´ ı)a; Princip si lze pamatovat mnemotechnickou pom˚ uckou. Osobn´ı, n´ akladn´ı, sportovn´ı vozy jsou auto, ale kaˇzd´e auto nen´ı osobn´ı.
6.6
Polymorfismus
Polymorfismus je jednou ze z´ akladn´ıch vlastnost´ı objektovˇe orientovan´eho programov´ an´ı. Urˇcuje chov´an´ı instance na z´ akladˇe jej´ıho typu. Z´ akladn´ı princip polymorfismu lze vystihnout takto: Potomek vˇzdy m˚ uˇze zastoupit pˇredka. Pomoc´ı referenˇcn´ı promˇenn´e potomka lze pracovat i s metodami pˇredka. Zkusme se zamyslet nad ot´ azkou, jak´ a z metod bude vyvol´ ana pro objekt rodiˇcovsk´e nebo odvozen´e tˇr´ıdy. Odpovˇed’ nen´ı jednoznaˇcn´ a. Existuj´ı dva pˇr´ıstupy: ˇ • Casn´ a vazba • Pozdn´ı vazba Za norm´aln´ıch podm´ınek se kompil´ ator ˇr´ıd´ı typem objektu: Auto a = new Auto(); Osobni o= new Osobni(); a.zastav(); o.zastav();
//volana metoda rodic. tridy //volana metoda odvoz. tridy
ˇ CNOST ˇ KAPITOLA 6. DEDI Tento pˇr´ıstup naz´ yv´ ame ˇcasnou neboli statickou vazbou. Kompil´ ator rozhoduje podle typu objektu, kter´a z metod bude spuˇstˇena, jiˇz pˇred pˇrekladem. Pokud nap´ıˇseme n´ asleduj´ıc´ı pˇr´ıkaz Auto a=new Osobni(); je vytvoˇrena nov´ a instance tˇr´ıdy Osobni, odkaz je konvertov´ an na typ Auto (vˇsimnˇeme si, ˇze potomek Osobni zastupuje pˇredka Auto). Aplikujeme -li na instanci metodu zastav() a.zastav(); je vol´ ana metoda odvozen´e tˇr´ıdy. Metoda je tedy vyvol´ ana na z´ akladˇe skuteˇcn´eho typu instance. Tento mechanismus naz´ yv´ ame pozdn´ı vazbou. Dynamick´a, neboli pozdn´ı vazba prov´ ad´ı rozhodov´ an´ı o tom, kter´ a z metod (rodiˇcovsk´ a nebo odvozen´ a) bude spuˇstˇena aˇz za bˇehu programu. Metoda je vyb´ır´ ana podle typu objektu, na kter´ y reference odkazuje. Tento postup naz´ yv´ ame polymorfismem.
Kapitola 7
V´ yjimky Doposud jsme pˇredpokl´ adali, ˇze naˇse programy budou fungovat za vˇsech situac´ı, tj. ˇze v nich nem˚ uˇze doj´ıt za bˇehu k chybˇe. Toto je vˇsak pomˇernˇe idealizovan´ y model, program´ator by mˇel m´ıt moˇznost reakce jak na chyby vlastn´ı (odmocnina ze z´ aporn´eho ˇc´ısla, dˇelen´ı nulou, atd.), tak na chyby vypl´ yvaj´ıc´ı z komunikace programu se sv´ ym okol´ım (ˇspatn´e zad´ an´ı hodnoty u form´atovan´eho vstupu, nenalezen´ı potˇrebn´eho souboru, atd.). Pokud by tyto stavy nebyly oˇsetˇreny, mohlo by doj´ıt ke ztr´at´am dat a z nich vypl´ yvaj´ıc´ım ˇskod´am. K takov´emu programu nebude m´ıt uˇzivatel d˚ uvˇeru a nebude ho pouˇz´ıvat, nav´ıc m˚ uˇze b´ yt i nebezpeˇcn´ y (t´ yk´a se to zejm´ena software pro pr˚ umyslov´e zpracov´an´ı dat). Pokud k takov´e chybˇe dojde, lze na n´ı reagovat r˚ uzn´ ymi zp˚ usoby. Program m˚ uˇzeme ukonˇcit a sdˇelit, ˇze doˇslo k chybˇe. Dojde vˇsak ke ztr´ atˇe dat, takov´e ˇreˇsen´ı je proto nevhodn´e. M˚ uˇzeme se tak´e pokusit oˇsetˇrit vˇsechny moˇzn´e chybov´e stavy, ke kter´ ym by potenci´alnˇe mohlo doj´ıt. Tato varianta je lepˇs´ı, v ˇradˇe pˇr´ıpad˚ u zabr´an´ıme ztr´at´am dat, jej´ı implementace vˇsak nen´ı jednoduch´a. Nav´ıc znepˇrehledˇ nujeme vlastn´ı zdrojov´ y zav´ adˇen´ım pomocn´ ych promˇenn´ ych indikuj´ıc´ıch, zda v´ ypoˇcet probˇehl u ´ spˇeˇsnˇe. Nejv´ yhodnˇejˇs´ı je pouˇzit´ı tzv. mechanismu v´yjimek. Umoˇzn ˇuje chybu zachytit a oˇsetˇrit ji na vhodn´em m´ıstˇe. Pro u ´ plnost uved’me, ˇze pr´ ace s v´ yjimkami v jazyce Java je podobn´a pr´aci s v´ yjimkami v jazyce C++, nav´ıc ho rozˇsiˇruje o nov´e principy. V z´ ajmu bezpeˇcnosti Java nut´ı program´atora pouˇz´ıvat u nˇekter´ ych potenci´alnˇe nebezpeˇcn´ ych konstrukc´ı v´ yjimky, jinak nen´ı moˇzn´e program zkompilovat. V´ yjimku m˚ uˇzeme definovat jako stav programu v okamˇziku, kdy dojde pˇri jeho vykon´av´an´ı k chybˇe. Pˇri vyvol´an´ı v´ yjimky v Javˇe je vytvoˇren objekt, kter´ y nese informaci o typu chyby (a mnoh´e dalˇs´ı informace). Na v´ yjimku JVM upozorn´ı zasl´ an´ım zpr´ avy ve formˇe chybov´eho hl´aˇsen´ı. Pro vyvol´an´ı v´ yjimky je ˇcasto pouˇz´ıv´an term´ın throw exception, tj. vyhozen´ı v´ yjimky; nˇekdy tuto ˇcinnost m˚ uˇzeme prov´adˇet ”umˇele”. Uk´azka v´ yjimky generovan´e JVM pˇri pokusu o konverzi ˇretˇezce na desetinn´e ˇc´ıslo. Exception in thread "main" java.lang.NumberFormatException: For input string: "dw" at sun.misc.FloatingDecimal. readJavaFormatString(FloatingDecimal.java:1224) at java.lang.Double.parseDouble(Double.java:510) at balicek.Nacti.getDouble(Nacti.java:31) at balicek.Obdelnik.(Obdelnik.java:13) at balicek.Main.main(Main.java:16)
7.1
Druhy v´ yjimek
V Javˇe existuj´ı tˇri z´ akladn´ı typy tˇr´ıd (potomk˚ u tˇr´ıdy Object), kter´e slouˇz´ı pro pˇrenos informac´ı o vznikl´ ych v´ yjimk´ach. Jsou pˇr´ım´ ymi potomky tˇr´ıdy Throwable. Jejich hierarchie vypad´a takto.
69
´ KAPITOLA 7. VYJIMKY
Obr´ azek 7.1: Hierarchie tˇr´ıd pro pr´ aci s v´yjimkami. Pod´ıvejme se podrobnˇeji na jejich popis. Tˇ r´ıda Throwable. Se tˇr´ıdou Throwable ve velk´e vˇetˇsinˇe pˇr´ıpad˚ u nepracujeme (pracujeme vˇsak s jej´ımi potomky), neposkytuje ˇz´ adn´e konkr´etn´ı informace o typu v´ yjimky. Tˇ r´ıda Error. Tˇr´ıda Error a v´ yjimky od n´ı odvozen´e se pouˇz´ıvaj´ı vˇetˇsinou pouze v souvislosti s chybami JVM. Tyto chyby nedok´ aˇzeme opravit, ani jim efektivnˇe pˇredch´ azet. V takov´em pˇr´ıpadˇe dojde k ukonˇcen´ı programu a zobrazen´ı pˇr´ısluˇsn´eho chybov´eho hl´ aˇsen´ı. Touto tˇr´ıdou se proto d´ ale zab´ yvat nebudeme. Tˇ r´ıda RuntimeException. S v´ yjimkami odvozen´ ymi od t´eto tˇr´ıdy m˚ uˇzeme jiˇz pracovat. Pˇredstavuj´ı v´ yjimky, kter´e vznikaj´ı za bˇehu programu. Typick´ ym pˇr´ıkladem jsou v´ yjimky vznikaj´ıc´ı jako d˚ usledek prov´adˇen´ı aritmetick´ ych operac´ı s nevhodn´ ymi operandy (napˇr. dˇelen´ı nulou, odmocnina ze z´ aporn´eho ˇc´ısla: ArithmeticException, atd.) nebo konverzn´ıch operac´ı s nevhodn´ ymi operandy (konverze textov´eho ˇretˇezce na ˇc´ıslo: NumberFormatException). Pomˇernˇe ˇcasto se jedn´ a o nevhodn´e vstupn´ı u ´daje zadan´e uˇzivatelem v m´ıstech, kde program´ ator zapomnˇel takto vznikl´e chyby oˇsetˇrit. V programu je proto vhodn´e tyto stavy oˇsetˇrit (nic n´ as k tomu vˇsak nenut´ı), aby napˇr. pˇri zad´ an´ı nevhodn´ ych vstupn´ıch u ´daj˚ u nedoˇslo ke ztr´ atˇe dat. V´ yjimky zaˇrazen´e do t´eto tˇr´ıdy naz´ yv´ame asynchronn´ı. Tˇ r´ıda Exception. V´ yjimky zaˇrazen´e do t´eto tˇr´ıdy je na rozd´ıl od v´ yjimek zaˇrazen´ ych do tˇr´ıdy RuntimeException nutn´e vˇzdy oˇsetˇrit, v opaˇcn´em pˇr´ıpadˇe nebude proveden pˇreklad. Jedn´ a se zejm´ena o potenci´alnˇe nebezpeˇcn´e operace t´ ykaj´ıc´ı se napˇr. prac´ı se soubory, form´ atovan´ ym vstupem, datab´ azemi. Java je proto pomˇernˇe bezpeˇcn´ y jazyk, nut´ı program´ atora na tato m´ısta v programu reagovat. V´ yjimky naz´ yv´ ame synchronn´ı, pracuje se s nimi stejnˇe jako s v´ yjimkami asynchronn´ımi.
7.2
Oˇ setˇ ren´ı v´ yjimek
V´ yjimky lze v Javˇe oˇsetˇrovat tˇremi z´ akladn´ımi zp˚ usoby: 1. Propagace v´ yjimky: v´ yjimka nen´ı oˇsetˇrena v metodˇe, ve kter´e vznikla, je pˇred´ ana do nadˇrazen´e u ´ rovnˇe. 2. Oˇsetˇren´ı metodou chr´ anˇen´ ych blok˚ u: V´ yjimka je oˇsetˇrena v metodˇe, ve kter´e vznikla.
´ KAPITOLA 7. VYJIMKY 3. Kombinace obou zp˚ usob˚ u: V´ yjimka (ˇc´ asteˇcnˇe) oˇsetˇrena v metodˇe, kde vznikla. D´ ale je pˇred´ana do nadˇrazen´e u ´ rovnˇe. Tˇret´ı metoda je nejˇcastˇeji pouˇz´ıv´ ana, umoˇzn ˇuje komplexn´ı obslouˇzen´ı v´ yjimky. Postupnˇe se pod´ıv´ ame na vˇsechny v´ yˇse uveden´e postupy.
7.2.1
Oˇ setˇ ren´ı v´ yjimky propagac´ı
Tento postup je pomˇernˇe jednoduch´ y, v´ yjimku neoˇsetˇrujeme v m´ıstˇe, kde vznikla, jej´ı zpracov´ an´ı pˇred´av´ame do nadˇr´ızen´e u ´ rovnˇe. Hierarchie pˇred´ av´ an´ı je n´ asleduj´ıc´ı: metoda->main->JVM. Pokud v´ yjimku neoˇsetˇr´ıme ”pˇred u ´rovn´ı” JVM, dojde k automatick´emu ukonˇcen´ı programu a zobrazen´ı informace o chybˇe. Tento pˇr´ıstup je ˇcasto pouˇz´ıv´ an, pokud opakovanˇe prov´ ad´ıme nˇejakou operaci (cyklus), a nechceme opakovanˇe chybu ˇreˇsit (v tˇele cyklu). Uˇzivatele tedy neinformujeme 50x o tom, ˇze k chybˇe doˇslo. Pˇred´ ame tuto informaci pˇri prvn´ım v´ yskytu v´ yjimky metodˇe main() a zde rozhodneme o dalˇs´ım bˇehu programu. V deklaraci hlaviˇcky metody pouˇzijeme kl´ıˇcov´e slovo throws s identifik´ atorem v´ yjimky, kterou chceme oˇsetˇrit. throws typ_vyjimky; Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad, se kter´ ym jsme se jiˇz sezn´ amili v kapitole vˇenovan´e form´ atovan´emu vstupu. Vytvoˇr´ıme tˇr´ıdu Nacti, realizuj´ıc´ı naˇc´ıt´ an´ı ˇretˇezc˚ u z form´ atovan´eho vstupu a jejich konverzi na ˇc´ıslo typu double. public class Nacti { private byte [] pole; public double getDouble() throws IOException { pole=new byte[128]; System.in.read(pole); String ret=new String(pole); ret=ret.trim(); double cislo=Double.valueOf(ret).doubleValue(); return cislo; } public static void main(String [] args) throws IOException { Nacti n=new Nacti(); double cislo=n.getDouble(); } } V hlaviˇcce metody getDouble() pˇribyl k´ od public double getDouble() throws IOException sdˇeluj´ıc´ı, ˇze metoda poˇc´ıt´ a, ˇze by pˇri jej´ım vykon´ av´ an´ı mohlo doj´ıt k v´ yjimce IOException. Mohla by b´ yt zp˚ usobena ˇspatnˇe proveden´ ymi nebo pˇreruˇsen´ ymi operacemi se standardn´ım vstupem. Tato v´ yjimka vˇsak, na rozd´ıl od NumberFormatException, neoˇsetˇruje konverzi ˇretˇezce, ve kter´em by se kromˇe ˇc´ıslic vyskytly dalˇs´ı znaky: p´ısmena, speci´ aln´ı znaky, ... (napˇr. uˇzivatel m´ısto 123 zad´ a 12#). Pokud by k takov´e v´ yjimce doˇslo, nebude na t´eto u ´rovni nijak ˇreˇsena, bude odsunuta do nadˇrazen´e u ´rovnˇe, tj. do metody main().
´ KAPITOLA 7. VYJIMKY public static void main(String [] args) throws IOException Zde nen´ı tak´e nijak ˇreˇsena, proto by program byl ukonˇcen JVM. Vhodnˇejˇs´ı by bylo v tomto m´ıstˇe napˇr. uˇzivateli sdˇelit, ˇze doˇslo k chybˇe vstupu (s t´ım se sezn´ am´ıme v n´ asleduj´ıc´ı kapitole). Kter´ y typ v´ yjimky bude oˇ setˇ ren? Upozornˇeme, ˇze t´ımto zp˚ usobem je oˇsetˇrena pouze v´ yjimka IOException a vˇsechny v´ yjimky od t´eto tˇr´ıdy odvozen´e. Uplatˇ nuje se zde princip, ˇze potomek m˚ uˇze zastoupit pˇredka. Pokud by doˇslo k ”jin´e” v´ yjimce, program se bude chovat, jako kdyby k´ od za throws neexistoval. Peˇcliv´eho program´ atora by mohlo napadnout, ˇze ˇreˇsen´ım by bylo oˇsetˇren´ı vˇsech chyb. Tˇech je vˇsak cca 30, takov´ y program by se stal nepˇrehledn´ ym a zbyteˇcnˇe sloˇzit´ ym. Vyplat´ı se proto strategie oˇsetˇrov´ an´ı pouze nejv´ıce bolav´ ych m´ıst programu. Jinou moˇznost´ı by bylo pouˇz´ıt spoleˇcn´eho pˇredka, tˇr´ıdu Exception. public static void main(String [] args) throws Exception V takov´em pˇr´ıpadˇe vˇsak nen´ı moˇzn´e jednoduˇse detekovat, k jak´e v´ yjimce doˇslo.
7.2.2
Oˇ setˇ ren´ı v´ yjimky metodou chr´ anˇ en´ ych blok˚ u
Tento postup umoˇzn ˇuje oˇsetˇrit v´ yjimku v m´ıstˇe, kde vznikla. Vyuˇz´ıv´ a tzv. chr´ anˇen´eho bloku, uvnitˇr kter´eho je uzavˇren k´ od, pˇri jehoˇz vykon´ av´ an´ı m˚ uˇze doj´ıt k v´ yjimce. Chr´ anˇen´ y blok je uveden pˇr´ıkazem try. Za n´ım n´ asleduje blok catch informuj´ıc´ı, jak´ y typ v´ yjimky bude oˇsetˇren. V pˇr´ıpadˇe v´ yskytu v´ yjimky v chr´anˇen´em bloku try (typ v´ yjimky mus´ı b´ yt shodn´ y s typem v´ yjimky v ˇc´ asti catch) dojde k jej´ımu zachycen´ı a zaˇcne se vykon´ avat blok catch. Konstrukce try-catch m˚ uˇze b´ yt doplnˇena i o nepovinn´ y blok finally, kter´ y se provede vˇzdy. try { //chraneny blok } catch (typ vyjimky) { //osetreni vyjimky } finally { //provede se vzdy } Vˇetˇsinou se pouˇz´ıv´ a konstrukce try-catch, blok finally je vyuˇz´ıv´ an ve specifick´ ych pˇr´ıpadech (napˇr. pˇri pr´ aci se soubory). Pokusme se upravit pˇredchoz´ı pˇr´ıklad tak, aby v okamˇziku vzniku v´ yjimky doˇslo k jej´ımu oˇsetˇren´ı v bloku catch. public class Nacti { private byte [] pole; public double getDouble() { try {
´ KAPITOLA 7. VYJIMKY pole=new byte[128]; System.in.read(pole); String ret=new String(pole); ret=ret.trim(); double cislo=Double.valueOf(ret).doubleValue(); return cislo; } catch (IOException e) { System.out.prinln("Chyba pri zadavani udaju"); return 0; } } public static void main(String [] args) { Nacti n=new Nacti(); double cislo=n.getDouble(); } } Pokud dojde pˇri operac´ıch se standardn´ım vstupem k v´ yjimce typu k v´ yjimce IOException, je oˇsetˇrena v bloku catch. T´ımto zp˚ usobem lze odchytit pouze v´ yˇse uvedenou v´ yjimku a v´ yjimky od t´eto tˇr´ıdy odvozen´e. Upozornˇeme, ˇze opˇet nebude odchycena pˇr´ıpadn´ a v´ yjimka vznikl´ a konverz´ı String na double. Oˇ setˇ ren´ a v´ yjimka. V´ yˇse uveden´e informace lze zobecnit. Jestliˇze je nalezen pˇr´ısluˇsn´ y blok catch a je do nˇej vstoupeno, povaˇzujeme v´ yjimku za oˇsetˇrenou. Pokud by doˇslo ke vzniku jin´eho typu v´ yjimky (tj. nebyl by nalezen odpov´ıdaj´ıc´ı blok catch), nebude v´ yjimka oˇsetˇrena. Blok catch by mˇel obsahovat nˇejak´ y v´ ykonn´ y k´ od, kter´ y vykon´ a akci v z´ avislosti na typu v´ yjimky (napˇr. informuje uˇzivatele, ˇze doˇslo k chybˇe). Pozor: nikdy nepouˇz´ıvejme pr´ azdn´e bloky catch, v takov´em pˇr´ıpadˇe by nedoˇslo k ˇz´ adn´e reakci na v´ yjimku. V pˇr´ıpadˇe, kdy bychom chtˇeli zachytit libovolnou v´ yjimku, museli bychom jako typ oˇsetˇrovan´e v´ yjimky pouˇz´ıt spoleˇcn´eho pˇredka, tˇr´ıdu Exception. catch (Exception e) { System.out.prinln("Doslo k nejake vyjimce"); return 0; } N´ aslednˇe vˇsak nen´ı moˇzn´e zjistit, k jak´emu typu v´ yjimky doˇslo, a na z´ akladˇe toho se rozhodnout, jak v´ yjimku oˇsetˇrit (r˚ uzn´e typy v´ yjimek zpravidla oˇsetˇrujeme r˚ uznˇe). V´ ypis informac´ı o v´ yjimce. Oˇsetˇr´ıme-li v´ yjimku konstrukc´ı try-catch, za bˇehu programu informace o (oˇsetˇren´e) v´ yjimce bˇeˇzn´ ym zp˚ usobem nez´ısk´ ame. Je vykon´ an blok catch, nedojde k zastaven´ı programu a v´ ypisu informace o v´ yjimce. Tyto informace lze z´ıskat dodateˇcnˇe pouˇzit´ım metody printStackTrace(). catch (NumberFormatException e) { e.printStackTrace(); } Z´ısk´ ame tak informace, kter´e lze pouˇz´ıt napˇr. pˇri ladˇen´ı programu.
´ KAPITOLA 7. VYJIMKY Kombinov´ an´ı v´ yjimek. Doposud jsme v souvislosti s tˇr´ıdou Nacti oˇsetˇrovali pouze v´ yjimky typu IOException a ”ignorovali” jsme v´ yjimky vznikl´e konverz´ı naˇcten´eho ˇretˇezce. Jeden blok try m˚ uˇze b´ yt oˇsetˇren nˇekolik bloky catch. Tento postup umoˇzn ˇ uje reagovat na v´ıce v´ yjimek, jejich poˇcet nen´ı v Javˇe omezen. Jakmile v´ yjimka sv´ ym typem odpov´ıd´ a typu v´ yjimky uveden´e v bloku catch, je tento blok n´ aslednˇe proveden. try { //nejaky kod } catch (NumberFormatException e) { //Osetreni vyjimky } catch (IOException e) { //Osetreni vyjimky } Pozor. Oˇsetˇrovan´e v´ yjimky mus´ı b´ yt seˇrazeny vzestupnˇe dle hierarchie. Pokud bychom tento postup nedodrˇzeli, v´ yjimky budou odchyceny v handleru “nadˇrazen´e” tˇr´ıdy a blok catch oˇsetˇruj´ıc´ı potomka takov´e tˇr´ıdy neprobˇehne; vznikne tak unreachable (nedostupn´ y) k´ od. Takov´ y k´ od se nikdy neprovede! try { //nejaky kod } catch (Exception e) //Predek, vyjimka bude odchycena zde { //Osetreni vyjimky } catch (NumberFormatException e) //Potomek, tento blok jiz neprobehne { //Osetreni vyjimky }
7.2.3
Oˇ setˇ ren´ı v´ yjimky metodou chr´ anˇ en´ ych blok˚ u a jej´ı pˇ red´ an´ı v´ yˇ se
Tato metoda je kombinac´ı pˇredchoz´ıch dvou postup˚ u. Umoˇzn ˇuje v´ yjimku oˇsetˇrit v m´ıstˇe, kde vznikla a n´ aslednˇe ji pˇredat v´ yˇse. V´ yhodou je fakt, ˇze na v´ yjimku lze reagovat opakovanˇe na r˚ uzn´ ych u ´rovn´ıch programu. Vyvol´ an´ı v´ yjimky. Nejprve se sezn´ am´ıme s kl´ıˇcov´ ym slovem throw, kter´e se pouˇz´ıv´ a pro vyvol´an´ı a n´ asledn´e ˇs´ıˇren´ı v´ yjimky. Obsahuje jako parametr odkaz na objekt nesouc´ı informaci o chybˇe. V´ yjimka je ˇs´ıˇrena dle v´ yˇse uveden´e hierarchie do ”nadˇrazen´ ych” komponent. Neplet’me si toto kl´ıˇcov´e slovo s kl´ıˇcov´ ym slovem throws. throw odkaz; Lze pouˇz´ıt odkaz na jiˇz existuj´ıc´ı objekt nebo vytvoˇrit nov´ y za pouˇzit´ı new.
´ KAPITOLA 7. VYJIMKY catch (IOException e) { throw e; //pouziti existujiciho odkazu } Druh´ a varianta se ˇcasto poj´ı s nˇejakou podm´ınkou. if (podminka) { throw new IOException; // vytvoreni noveho odkazu } Postup ˇs´ıˇren´ı v´ yjimky prakticky naznaˇc´ıme pˇri v´ ypoˇctu faktori´ alu. Tˇr´ıda Faktorial bude obsahovat dvˇe metody: nacti() realizuj´ıc´ı naˇcten´ı hodnoty z form´ atovan´eho vstupu a faktorial() pro v´ ypoˇcet faktori´alu. Pokud je na vstupu zad´ an ˇretˇezec obsahuj´ıc´ı jin´ y znak neˇz ˇc´ıslo, dojde k vyvol´ an´ı v´ yjimky IOException, kter´ a je n´aslednˇe pomoc´ı pˇr´ıkazu throw pˇred´ ana v´ yˇse. public int nacti() throws IOException { try { byte [] pole=new byte[128]; System.in.read(pole); String ret=new String(pole); ret=ret.trim(); int cislo=Double.valueOf(ret).doubleValue(); return cislo; } catch (IOException e) { System.out.println("Chyba."); throw e; } } Vlastn´ı v´ ypoˇcet faktori´ alu je realizov´ an za pouˇzit´ı rekurze takto: public int faktorial (int n) { if (n>1) return n*faktorial(n-1); else return 1; } V´ ypoˇcet faktori´ alu probˇehne v metodˇe main(). Pokud nebyla vyvol´ ana v´ yjimka, je spoˇctena hodnota faktori´ alu v bloku try. V pˇr´ıpadˇe, kdy doˇslo k ˇs´ıˇren´ı v´ yjimky pˇr´ıkazem throw, je nalezen odpov´ıdaj´ıc´ı blok catch, v´ yjimka je opakovanˇe oˇsetˇrena a pomoc´ı metody printStackTrace() jsou uˇzivateli sdˇeleny informace o v´ yjimce. Pokud je zad´ ano ˇc´ıslo ˇc´ıslo neleˇz´ıc´ı v intervalu <0, 40> je vyvol´ ana v´ yjimka ArithmeticException. public static void main(String[] args) { try
´ KAPITOLA 7. VYJIMKY { Faktorial f=new Faktorial(); int c=f.nacti(); if ((c<0)||(c>40)) throw new ArithmeticException; int fakt=f.faktorial(c); System.out.println(c+"!="+fakt); } catch (IOException e) { System.out.println("Chyba pri vstupu dat."); e. printStackTrace(); } catch (ArithmeticException e) { System.out.println("Hodnota nelezi v intervalu."); e. printStackTrace(); } }
7.3
Tvorba vlastn´ıch v´ yjimek
V Javˇe lze vytvoˇrit vlastn´ı tˇr´ıdy v´ yjimek. Postup se pouˇz´ıv´ a v pˇr´ıpadˇe, kdy chceme sami definovat a oˇsetˇrit u jin´e tˇr´ıdy stavy, kter´e budeme povaˇzovat za chybov´e. Takov´eho stavu m˚ uˇze b´ yt dosaˇzeno pˇri splnˇen´ı/nesplnˇen´ı nˇejak´e podm´ınky (napˇr. vstupn´ı hodnoty leˇz´ıc´ı mimo zadan´ y interval) a nen´ı moˇzno ho odchytit bˇeˇzn´ ym mechanismem v´ yjimek, se kter´ ym jsme se sezn´ amili v´ yˇse. Tyto tˇr´ıdy budou vytv´ aˇreny dˇedˇen´ım od tˇr´ıdy Exception, bude se jednat o synchronn´ı v´ yjimky; princip ˇ jejich oˇsetˇrov´ an´ı je stejn´ y. Casto je pouˇz´ıv´ ame proto, abychom odliˇsili chybov´e stavy “skuteˇcn´e” (konverzn´ı, aritmetick´e operace) a chybov´e stavy n´ ami “navrˇzen´e” (pˇri splnˇen´ı ˇci nesplnˇen´ı nˇejak´e podm´ınky), kdy by bˇeh programu (tj. v´ ypoˇcet) nemohl efektivnˇe pokraˇcovat. Praktick´ y postup uk´ aˇzeme naznaˇc´ıme pˇri v´ ypoˇctu faktori´ alu, kdy vstupn´ı u ´daje budou muset leˇzet v intervalu <0,40>. Na rozd´ıl od pˇredchoz´ıho pˇr´ıkladu nebudeme volat v´ yjimku tˇr´ıdy ArithmeticException, ale v´ yjimku tˇr´ıdy vlastn´ı, kterou nazveme FaktorialException. public class FactorialException extends Exception { public FactorialException() { super ("Zadana hodnota mimo interval"); } } Tˇr´ıda ArithmeticException obsahuje konstruktor volaj´ıc´ı konstruktor rodiˇcovsk´e tˇr´ıdy Exception s parametrem pˇredstavuj´ıc´ım ˇretˇezec nesouc´ı informaci pro uˇzivatele. Pokud vstupn´ı hodnota neleˇz´ı v intervalu <0,40> je vyvol´ ana v´ yjimka tˇr´ıdy FactorialException. Upravme metodu faktorial() tak, aby na tento stav reagovala. public int faktorial (int n) throws FactorialException { if (n>40)||(n<0) throw new FactorialException();
´ KAPITOLA 7. VYJIMKY else if n>0 return n*faktorial(n-1); else return 1; } V metodˇe main() nesm´ıme zapomenout oˇsetˇrit v´ yjimku tˇr´ıdy FactorialException v bloku catch. public static void main(String[] args) { try { Faktorial f=new Faktorial(); int c=f.nacti(); int fakt=f.faktorial(c); System.out.println(c+"!="+fakt); } catch (IOException e) { System.out.println("Chyba pri vstupu dat."); e. printStackTrace(); } catch (FactorialException e) { System.out.println("Nelze vypocitat faktorial"); e. printStackTrace(); } } Zad´ ame -li hodnotu leˇz´ıc´ı mimo zadan´ y interval, obdrˇz´ıme chybov´e hl´ aˇsen´ı o v´ yjimce. Nelze vypocitat faktorial Balicek.FaktorialException: Zadana hodnota mimo interval at Balicek.Obdelnik.(Faktorial.java:14) at Balicek.Main.main(Main.java:29) Z´ avˇ er. Jak jsme z v´ yˇse uveden´ ych pˇr´ıklad˚ u vidˇeli, pr´ ace s v´ yjimkami v Javˇe je velmi podobn´ a pr´aci s v´ yjimkami v jazyce C++. Java je na rozd´ıl od C++ bezpeˇcnˇejˇs´ı, prov´ ad´ı kontrolu oˇsetˇren´ı v´ yjimek na u ´rovni kompil´ atoru, nikoliv jen jejich oˇsetˇren´ı za bˇehu.
Kapitola 8
Rozhran´ı Rozhran´ı je n´astrojem, kter´ y umoˇzn ˇ uje ˇc´ asteˇcnˇe nahradit neexistenci v´ıcen´asobn´e dˇediˇcnosti v Javˇe. Pr´ace s n´ım je podobn´ a pr´ aci s abstraktn´ımi tˇr´ıdami. V rozhran´ı deklarujeme metody, o jejich definici se mus´ı postarat tˇr´ıda rozhran´ı implementuj´ıc´ı. Pˇri definici mus´ı b´ yt pˇrekryty vˇsechny metody deklarovan´e v rozhran´ı, nikoliv pouze nˇekter´e. Rozhran´ı vˇsak na rozd´ıl od tˇr´ıdy nesm´ı obsahovat deklarace promˇenn´ ych s v´ yjimkou konstant. Tˇr´ıda m˚ uˇze implementovat v´ıce neˇz jedno rozhran´ı. M˚ uˇzeme si ho tedy pˇredstavit jako abstraktn´ı tˇr´ıdu tvoˇrenou pouze abstraktn´ımi metodami. Kdy rozhran´ı pouˇz´ıt? Nejˇcastˇeji v pˇr´ıpadech, kdy tˇr´ıda implementuje vlastnosti nˇekolika jin´ ych tˇr´ıd nebo m´ame vytvoˇrit v´ıce tˇr´ıd s podobn´ ymi vlastnostmi. V takov´ ych pˇr´ıpadech m˚ uˇze b´ yt klasick´e ˇreˇsen´ı s vyuˇzit´ım dˇediˇcnosti pomˇernˇe sloˇzit´e, vznik´ a sloˇzit´ a struktura vz´ajemnˇe dˇed´ıc´ıch tˇr´ıd. V souˇcasn´e dobˇe je rozhran´ı vyuˇz´ıv´ano v´ıce neˇz abstraktn´ı tˇr´ıdy.
8.1
Implementace jednoho rozhran´ı tˇ r´ıdou
Pr´ace s rozhran´ım a jeho deklarace pˇripom´ın´a pr´aci s tˇr´ıdami. Rozhran´ı lze vytvoˇrit s vyuˇzit´ım kl´ıˇcov´eho slova interface konstrukc´ı public interface identifikator {seznam_metod}; Modifik´ator public znamen´ a, ˇze je rozhran´ı pˇr´ıstupn´e. Stejnˇe jako tˇr´ıda mus´ı b´ yt uloˇzeno v souboru stejn´eho jm´ena jako identifik´ ator rozhran´ı. Pˇr´ıklad rozhran´ı. public interface Rozhrani { public void metoda1(); public void metoda2(); } Ve sv´em tˇele obsahuje deklarace metod, kter´e mus´ı b´ yt v tˇele tˇr´ıdy implementuj´ıc´ı rozhran´ı pˇrekryty, nepostaˇcuje jejich pˇret´ıˇzen´ı. Pokud tak neuˇcin´ıme, program nep˚ ujde spustit. Implementace rozhran´ı ve tˇr´ıdˇe je provedena s pouˇzit´ım pˇr´ıkazu implements takto implements rozhrani;
78
KAPITOLA 8. ROZHRAN´I Tˇr´ıda implementuj´ıc´ı rozhran´ı Rozhrani m˚ uˇze vypadat takto: public class Trida implements Rozhrani { public void metoda1() { //predefinovani metody } public void metoda2() { //predefinovani metody } .... } V´ yjimku pˇredstavuje pouˇzit´ı abstraktn´ı tˇr´ıdy, abstraktn´ı tˇr´ıda implementuj´ıc´ı rozhran´ı nemus´ı prov´ adˇet pˇredefinov´ an´ı metod rozhran´ı. Tato konstrukce vˇsak nen´ı pˇr´ıliˇs ˇcasto pouˇz´ıv´ ana. public abstract class Trida implements Rozhrani { .... } Pr´ ace s rozhran´ım. Pr´ aci s rozhran´ım si uk´ aˇzeme na konkr´etn´ım pˇr´ıkladu. Vytvoˇr´ıme rozhran´ı Zvirata, tvoˇren´em jedinou metodou pocetNohou() vracej´ıc´ı poˇcet nohou zv´ıˇrete. public interface Zvire { public int pocetNohou(); } Rozhran´ı bude implementov´ ano dvˇema tˇr´ıdami: Selma a Ptak. V kaˇzd´e z tˇechto tˇr´ıd pˇredefinujeme metodu tak, aby vracela spr´ avn´ y poˇcet nohou uloˇzen´ y ve stejnojmenn´e promˇenn´e inicializovan´e v implicitn´ım konstruktoru. public class Selma implements Zvire { private int pocet_nohou; public Selma() {this.pocet_nohou=4;} public int pocetNohou() {return this.pocet_nohou;} } public class Ptak implements Zvire{ private int pocet_nohou; public Ptak() {this.pocet_nohou=2;} public int pocetNohou() {return this.pocet_nohou;} } Ve tˇr´ıdˇe Main() vytvoˇr´ıme instance obou tˇr´ıd a aplikujeme na nˇe metodu pocetNohou(). V prvn´ım pˇr´ıpadˇe obdrˇz´ıme hodnotu 4, ve druh´em 2, coˇz odpov´ıd´ a skuteˇcnosti :-).
KAPITOLA 8. ROZHRAN´I public static void main(String[] args) { Selma s=new Selma(); Ptak p=new Ptak(); System.out.println(s.pocetNohou()); System.out.println(p.pocetNohou()); } Promˇ enn´ a rozhran´ı. Ve tˇr´ıdˇe implementuj´ıc´ı rozhran´ı je moˇzn´e vytvoˇrit promˇennou tohoto rozhran´ı ve formˇe referenˇcn´ı promˇenn´e, v dalˇs´ım kroku j´ı zpravidla inicializujeme objektem stejn´eho typu. S takto vytvoˇrenou instanc´ı lze pracovat, m´ a nˇekter´e zaj´ımav´e vlastnosti (viz d´ ale). Zvire z1=new Selma(); Zvire z2=new Ptak(); Aplikujeme-li na instanci metodu pocetNohou(), spust´ı se metoda pˇr´ısluˇsej´ıc´ı tˇr´ıdˇe dle typu instance. Tato vlasnost je typick´ a pro i dˇediˇcnost. z1.pocetNohou(); //Pocet nohou selmy z2.pocetNohou(); //Pocet nohou ptaka Instance rozhran´ı a tˇr´ıd implementuj´ıc´ıch rozhran´ı m˚ uˇzeme vz´ ajemnˇe pˇriˇrazovat: Instanci rozhran´ı m˚ uˇzeme pˇriˇradit pˇr´ımo instanci tˇr´ıdy implementuj´ıc´ı rozhran´ı. Opaˇcn´ y postup, tj. pˇriˇrazen´ı instance rozhran´ı instanci tˇr´ıdy, funguje pouze s explicitn´ım pˇretypov´ an´ım. z1=s; //Pretypovani potomka na rodice primo z1=p; //Pretypovani potomka na rodice primo s=(Selma) z1; //Pretypovani rodice na potomka explicitne p=(Ptak) z1; //Pretypovani rodice na potomka explicitne Prvn´ı pˇr´ıpad pˇredstavuje pˇretypov´ an´ı potomka na rodiˇce, druh´ y pˇretypov´ an´ı rodiˇce na potomka. Tento pˇr´ıstup je stejn´ y, s jak´ ym jsme se jiˇz setkali v kapitole vˇenovan´e dˇediˇcnosti tˇr´ıd. Instance rozhran´ı a pˇ r´ıstup k metod´ am. S instanc´ı typu rozhran´ı deklarovan´e ve tˇr´ıdˇe implementuj´ıc´ı rozhran´ı m˚ uˇzeme pˇristupovat ke vˇsem metod´ am deklarovan´ ych ve stejn´em rozhran´ı. Nelze pˇristupovat k metod´ am, kter´e jsou definov´ any pouze v tˇechto tˇr´ıd´ ach ani k jej´ım promˇenn´ ym, rozhran´ı je nezn´ a. S vyuˇzit´ım instance rozhran´ı m˚ uˇzeme tedy manipulovat pouze s metodami tˇr´ıd v rozhran´ı implementovan´ ych. Tato vlastnost je v praxi ˇcasto pouˇz´ıv´ ana. Vytvoˇrme metodu rychlost() ve tˇr´ıdˇe Selma vracej´ıc´ı jej´ı rychlost. public int rychlost() { return this.rychlost; } Na instanci tˇr´ıdy Selma m˚ uˇzeme metodu aplikovat, pˇri pokusu o aplikaci metody na instanci z1, kompil´ator ozn´ am´ı chybu. s.rychlost(); //spravne z1.rychlost(); //rozhrani metodu nezna Na z´ akladˇe v´ yˇse uveden´ ych poznatk˚ u m˚ uˇzeme prohl´ asit, ˇze pr´ ace s rozhran´ımi se pˇr´ıliˇs neliˇs´ı od pr´ace s abtraktn´ımi tˇr´ıdami.
KAPITOLA 8. ROZHRAN´I
8.2
Implementace v´ıce rozhran´ı tˇ r´ıdou
Tˇr´ıda m˚ uˇze implementovat v´ıce neˇz jedno rozhran´ı, poˇcet implementovan´ ych rozhran´ı nen´ı omezen. Tento pˇr´ıstup ˇc´ asteˇcnˇe nahrazuje v´ıcen´ asobnou dˇediˇcnost zn´ amou napˇr. z jazyka C++. V takov´em pˇr´ıpadˇe uv´ad´ıme za kl´ıˇcov´ ym slovem implements seznam vˇsech implementovan´ ych rozhran´ı oddˇelen´ ych ˇc´ arkou. Vˇsechny metody implementovan´ ych rozhran´ı mus´ı b´ yt ve tˇr´ıdˇe pˇredefinov´ any public class Trida implements Rozhrani1, Rozhrani2, Rozhrani3 { .... } Vytvoˇrme rozhran´ı s n´ azvem Savec, kter´e bude obsahovat jedinou metodu jeSavec() vracej´ı informaci, zda je dan´e zv´ıˇre savec. public interface Savec { public String jeSavec(); } Obˇe tˇr´ıdy Selma a Ptak budou implementovat rozhran´ı Zvire a Savec. Musej´ı pˇredefinov´ avat metody pocetNohou() a jeSavec(). public class Selma implements Zvire, Savec { private int pocet_nohou; private String savec; public Selma() { this.pocet_nohou=4; this.savec="Je savec"; } public int pocetNohou() {return this.pocet_nohou;} public String jeSavec() {return this.savec;} } public class Ptak implements Zvire, Savec{ private int pocet_nohou; private String savec; public Ptak() { this.pocet_nohou=2; this.savec="Neni savec"; } public int pocetNohou() {return this.pocet_nohou;} public String jeSavec() {return this.savec;} Metoda main() vypad´ a takto. public static void main(String[] args) { Selma s=new Selma(); Ptak p=new Ptak(); System.out.println(s.pocetNohou()); System.out.println(p.pocetNohou());
KAPITOLA 8. ROZHRAN´I System.out.println(s.jeSavec()); System.out.println(p.jeSavec()); } Pro instanci s vrac´ı informaci, ˇze je savcem, pro instanci p, ˇze savcem nen´ı.
8.3
Rozhran´ı a dˇ ediˇ cnost
Pr´ aci s rozhran´ım je moˇzno kombinovat s dˇediˇcnost´ı tˇr´ıd. Pokud tˇr´ıda implementuje rozhran´ı a odvod´ıme od takov´e tˇr´ıdy potomky, budou metody rozhran´ı pˇr´ıstupn´e i v odvozen´ ych tˇr´ıd´ ach. Pokud v nich neprovedememe jej´ı pˇredefinov´ an´ı, bude se vˇzdy jednat o metodu rodiˇce. V odvozen´ ych tˇr´ıd´ ach jiˇz nen´ı povinnost metody rozhran´ı pˇredefinov´ avat, m´ ame vˇsak tuto moˇznost k dispozici. Vytvoˇr´ıme tˇr´ıdu Netopyr, kter´ a bude potomkem tˇr´ıdy Ptak (netop´ yr pˇrece tak´e l´et´ a :-))). public class Netopyr extends Ptak { public Netopyr() { } Pokud bychom v metodˇe main() vytvoˇrili novou instanci typu Netopyr a metodou jeSavec() zjiˇst’ovali, zda je netop´ yr savcem, obdrˇzeli bychom z´ apornou odpovˇed’. Netopyr n=new Netopyr(); System.out.println(n.jeSavec()); Metodu jeSavec() proto budeme muset v odvozen´e tˇr´ıdˇe pˇredefinovat. public class Netopyr extends Ptak { private String savec; public Netopyr() {} public String jeSavec() {return this.savec;} } Pot´e jiˇz obdrˇz´ıme spr´ avn´ y a oˇcek´ avan´ y v´ ysledek: netop´ yr je savec.
8.4
Vnitˇ rn´ı tˇ r´ıdy
Tˇr´ıdy jsou tvoˇreny komponentami pˇredstavovan´ ymi metodami a datov´ ymi poloˇzkami. V deklaraci jedn´e tˇr´ıdy se m˚ uˇze vyskytnout i deklarace jin´e tˇr´ıdy. Takovou tˇr´ıdu oznaˇcujeme jako vnitˇrn´ı, popˇr. vnoˇrenou. Tˇr´ıda, kter´ a ji obaluje, se naz´ yv´ a vnˇejˇs´ı. Tento typ tˇr´ıd je v Javˇe pouˇz´ıv´ an nejˇcastˇeji pˇri pr´ aci s grafick´ ym rozhran´ım. Moˇznost pouˇz´ıv´ an´ı vnitˇrn´ıch tˇr´ıd je v Javˇe k dispozici od JDK 1.1. Zm´ın´ıme se o nich pouze velmi struˇcnˇe, podrobnosti lze nal´ezt ve specializovan´e literatuˇre. Deklarace vnˇejˇs´ı a vnitˇrn´ı tˇr´ıdy vypad´ a takto
KAPITOLA 8. ROZHRAN´I class vnejsi { ... class vnitrni { ... } } Pˇ r´ıstup ke komponent´ am vnitˇ rn´ı a vnˇ ejˇ s´ı tˇ r´ıdy. Vnitˇrn´ı tˇr´ıda m˚ uˇze pˇr´ımo pˇristupovat ke vˇsem komponent´ am vnˇejˇs´ı tˇr´ıdy, tj. jak k metod´ am, tak promˇenn´ ym. Ke komponent´ am vnitˇrn´ı tˇr´ıdy vˇsak z vnˇejˇs´ı tˇr´ıdy nen´ı moˇzn´e pˇristupovat pˇr´ımo ani prostˇrednictv´ım referenˇcn´ı promˇenn´e vnˇejˇs´ı tˇr´ıdy, n´ ybrˇz pouze prostˇrednictv´ım referenˇcn´ı promˇenn´e vnitˇrn´ı tˇr´ıdy. Pˇristupujeme-li ke komponent´ am vnˇejˇs´ı tˇr´ıdy z jin´e tˇr´ıdy, je tak moˇzn´e uˇcinit bˇeˇzn´ ym zp˚ usobem prostˇrednictv´ım referenˇcn´ı promˇenn´e. Ke komponent´ am vnitˇrn´ı tˇr´ıdy vˇsak z jin´e neˇz vnˇejˇs´ı tˇr´ıdy nen´ı moˇzn´e pˇristoupit. Tento typ tˇr´ıd je v Javˇe pouˇz´ıv´ an nejˇcastˇeji pˇri pr´ aci s grafick´ ym rozhran´ım. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad. Vytvoˇr´ıme vnˇejˇs´ı a vnitˇrn´ı tˇr´ıdu, vnˇejˇs´ı tˇr´ıda m´ a jednu datovou poloˇzku typu int a, vnitˇrn´ı tˇr´ıda m´ a jednu datovou poloˇzku typu int b. class Vnejsi { private int a; public Vnejsi() {} class Vnitrni { private int b; public void setB(int b) {this.b = b;} public void Nastav1() { b=10; //OK setB(10); //OK a=10; //OK setA(10); //OK Vnejsi v=new Vnejsi(); //OK v.setA(10);a=10; // OK setA(10); //OK Vnejsi v=new Vnejsi(); //OK } } public void setA(int a) {this.a = a;} public void Nastav2() { b=10; //spatne setB(10); //spatne a=10; //OK setA(10); //OK Vnejsi v=new Vnejsi(); //OK v.setA(10);//OK Vnitrni v2=new Vnitrni(); //OK
KAPITOLA 8. ROZHRAN´I v2.setB(10);Vnitrni v=new Vnitrni(); Vnejsi t2=new Vnejsi(); //OK
//OK
} } Pokud se budeme pokouˇset pˇristoupit ke komponent´ am vnitˇrn´ı a vnˇejˇs´ı tˇr´ıdy z jin´e tˇr´ıdy, v´ ysledek bude vypadat takto. public class Pristup { ... public static void main(String[] args) { Vnejsi t=new Vnejsi(); //OK Vnitrni v=new Vnitrni(); //Spatne } } V Javˇe jsou vnitˇrn´ı tˇr´ıdy pouˇz´ıv´ any nejˇcastˇeji spoleˇcnˇe s rozhran´ım.
8.4.1
Vnitˇ rn´ı tˇ r´ıdy a rozhran´ı
Vnitˇrn´ı tˇr´ıdy zpravidla implementuj´ı rozhran´ı. Vnitˇrn´ı tˇr´ıda implementuj´ıc´ı rozhran´ı mus´ı pˇredefinovat vˇsechny metody rozhran´ı. Metody rozhran´ı budou z vnˇejˇs´ı tˇr´ıdy pˇr´ıstupn´e pouze pˇres referenˇcn´ı promˇennou typu rozhran´ı, nebude je moˇzno volat pˇres referenˇcn´ı promˇennou vnˇejˇs´ı tˇr´ıdy. Pro ilustraci pr´ ace s rozhran´ım pouˇzijeme tˇr´ıdy z pˇredch´ azej´ıc´ı kapitoly. Vytvoˇr´ıme opˇet tˇr´ıdu Vnejsi a Vnitrni, druh´ a z nich implementuje rozhran´ı Zvire. public class Vnejsi { public Vnejsi(){ Zvire z1 =new Vnitrni(); //OK Vnitrni v=new Vnitrni(); //OK Zvire z2 =new Zvire(); //Spatne } class Vnitrni implements Zvire { private int pocet_nohou; public Vnitrni() {this.pocet_nohou=4;} public int pocetNohou() {return pocet_nohou;} } } Pˇ r´ıstup k pˇ redefinovan´ ym metod´ am z jin´ e neˇ z vnˇ ejˇ s´ı tˇ r´ıdy. V tomto pˇr´ıpadˇe se situace stane sloˇzitˇejˇs´ı. Vˇsimnˇeme si, ˇze pro pˇr´ıstup k pˇredefinovan´ ym metod´ am rozhran´ı z jin´e neˇz vnˇejˇs´ı tˇr´ıdy nem˚ uˇzeme pouˇz´ıt instanci vnˇejˇs´ı tˇr´ıdy ani vnitˇrn´ı tˇr´ıdy, ani rozhran´ı: public class Pristup { ... Vnejsi v1=new Vnejsi(); //OK v1.pocetNohou(); //Spatne
KAPITOLA 8. ROZHRAN´I Vnitrni v2=new Vnitrni(); //Spatne Zvire z1=new Vnejsi(); //Spatne Zvire z2=new Vnitrni(); //Spatne } } V takov´em pˇr´ıpadˇe budeme muset zdrojov´ y k´ od ponˇekud upravit. Jedin´ a “spr´ avn´ a” konstrukce umoˇzn ˇuje vytvoˇrit instanci tˇr´ıdy Vnejsi. Mohli bychom vytvoˇrit metodu, kter´ a by prostˇrednictv´ım metody t´eto instance vracela instanci tˇr´ıdy Vnitrni. public class Vnejsi { public Vnejsi(){ } public Vnitrni vratInstanci(){return new Vnitrni()} class Vnitrni implements Zvire { private int pocet_nohou; public Vnitrni() {this.pocet_nohou=4;} public int pocetNohou() {return pocet_nohou;} } } Upraven´ y k´ od tˇr´ıdy Pristup bude vypadat takto public class Pristup { ... Vnejsi v1=new Vnejsi(); //OK (v1.vratInstanci()).pocetNohou(); } }
8.4.2
Anonymn´ı vnitˇ rn´ı tˇ r´ıdy
V praxi je ˇcasto pouˇz´ıv´ an koncept tzv. anonymn´ıch vnitˇrn´ıch tˇr´ıd. Ten vych´ az´ı z faktu, ˇze v metodˇe main() vnˇejˇs´ı tˇr´ıdy n´ as nezaj´ım´ a jm´eno vnitˇrn´ı tˇr´ıdy, ale jen jej´ı instance. V´ ysledn´ y k´ od vˇsak neb´ yv´ a pˇr´ıliˇs pˇrehledn´ y. Zmˇena se bude t´ ykat pouze metody vratInstanci(). V t´eto metodˇe nebudeme vytv´ aˇret instanci vnitˇrn´ı tˇr´ıdy, ale instanci rozhran´ı. Budeme volat konstruktor rozhran´ı, uvnitˇr leˇz´ı jedin´ a pˇredefinovan´ a metoda pocetNohou(). public Vnitrni vratInstanci() { return new Zvire() { public int pocetNohou() {return pocet_nohou;}; } } Tento pˇr´ıstup je pouˇz´ıv´ an pˇri pr´ aci s grafick´ ym uˇzivatelsk´ ym rozhran´ım Swing (ale i AWT) v Javˇe, je nutn´e se s n´ım alespoˇ n r´ amcovˇe sezn´ amit. Konkr´etnˇe slouˇz´ı pro oˇsetˇrov´ an´ı ud´ alost´ı pˇrich´ azej´ıc´ıch od v´ıce komponent stejn´eho typu, kdy s vyuˇzit´ım anonymn´ıch vnitˇrn´ıch tˇr´ıd rozliˇsujeme p˚ uvodce ud´ alosti.
KAPITOLA 8. ROZHRAN´I Pˇ reklad programu s anonymn´ımi vnitˇ rn´ımi tˇ r´ıdami. Pˇri pˇrekladu programu obsahuj´ıc´ıho anonymn´ı vnitˇrn´ı tˇr´ıdu kromˇe souboru Vnejsi.class vznik´ a i soubor Vnejsi$.class obsahuj´ıc´ı k´ od anonymn´ı vnitˇrn´ı tˇr´ıdy. Nezapomeˇ nme tedy pˇri distribuci programu obsahuj´ıc´ıho anonymn´ı vnitˇrn´ı tˇr´ıdy pˇriloˇzit vˇsechny potˇrebn´e soubory.
Kapitola 9
Dynamick´ e datov´ e struktury Prvn´ı ot´azka, kter´ a zaˇc´ınaj´ıc´ıho program´atora ˇcasto napadne, zn´ı: K ˇcemu lze pouˇz´ıt dynamick´e datov´e struktury? Takov´ y uˇzivatel jiˇz um´ı pracovat s polem jak primitivn´ım datov´ ych typ˚ u, tak i s polem objekt˚ u. Zd´anlivˇe tedy nevid´ı d˚ uvod k pouˇzit´ı dynamick´ ych datov´ ych struktur. Ale co kdyˇz nastane situace, kdy bude cht´ıt do jiˇz vytvoˇren´eho pole pˇridat dalˇs´ı prvek? Nep˚ ujde to, protoˇze d´elka pole je definov´ana pˇri jeho vytvoˇren´ı, tuto hodnotu nelze za bˇehu programu mˇenit. Jakmile je d´elka pole pˇrekroˇcena, JVM n´as o t´eto situaci informuje vyvol´ an´ım v´ yjimky. V takov´em pˇr´ıpadˇe je v´ yhodn´e vyuˇz´ıt dynamick´ ych datov´ ych struktur. Dynamick´e datov´e struktury pouˇz´ıv´ ame pro ukl´ad´an´ı takov´ ych dat, u kter´ ych pˇredem nezn´ame rozsah. Dynamick´e datov´e struktury mohou za bˇehu mˇenit svoji velikost a poˇcet prvk˚ u v nich uloˇzen´ ych. Podporuj´ı nav´ıc nˇekter´e pokroˇcil´e operace s uloˇzen´ ymi daty; data lze tˇr´ıdit, transponovat, odstraˇ novat duplicitn´ı prvky, atd. Dynamick´ e datov´ e struktury a Java. Dynamick´e datov´e struktury nalezneme ve vˇetˇsinˇe programovac´ıch jazyk˚ u.1 Na rozd´ıl od jazyka C++, kdy se s dynamick´ ymi datov´ ymi strukturami zach´az´ı ponˇekud nestandardnˇe, v Javˇe n´ as ˇz´ adn´e pˇrekvapen´ı neˇcek´a. Pracujeme s nimi objektovˇe, dynamick´e datov´e struktury se chovaj´ı jako objekty. Tˇr´ıdy dynamick´ ych datov´ ych struktur najdeme v bal´ıˇcku java.util. Tyto tˇr´ıdy b´ yvaj´ı nˇekdy naz´ yv´ any jako tzv. kontejnerov´e tˇr´ıdy. Jsou analogi´ı ke skuteˇcn´emu kontejneru, do kter´eho m˚ uˇzeme vˇeci odhazovat nebo z nˇej jin´e vˇeci vyb´ırat :-).
ˇ arkovanou ˇcarou zn´ Obr´ azek 9.1: Hierarchick´ a struktura rozhran´ı Collection. C´ azornˇena rozhran´ı, plnou ˇcarou tˇr´ıdy, kter´e je implementuj´ı. 1 Pˇ redpokl´ ad´ ame,
ˇ ze ˇ cten´ aˇr je sezn´ amen se z´ akladn´ımi typy dynamick´ ych datov´ ych struktur, nebudeme je popisovat.
87
´ DATOVE ´ STRUKTURY KAPITOLA 9. DYNAMICKE Kontejnerov´ e tˇ r´ıdy a rozhran´ı. V Javˇe je princip pr´ ace s kontejnerov´ ymi tˇr´ıdami na prvn´ı pohled ponˇekud sloˇzitˇejˇs´ı. Z´ akladem jsou rozhran´ı, kter´e jsou implementov´ ana nˇekolika tˇr´ıdami. Instance tˇechto tˇr´ıd pˇredstavuj´ı kontejnery. Rozhran´ı a tˇr´ıdy vytv´ aˇrej´ı stromovou strukturu, kter´ a je zn´ azornˇena na obr. 9.1 a 9.2. Existuj´ı dvˇe z´ akladn´ı rozhran´ı implementovan´ a kontejnerov´ ymi tˇr´ıdami: • Collection Rozhran´ı Collection implementuj´ı rozhran´ı List a Set. List pˇredstavuje mnoˇzinu samostatn´ ych prvk˚ u uspoˇr´ adan´ ych dle urˇcit´eho kl´ıˇce Set mnoˇzinu neuspoˇr´ adan´ ych prvk˚ u. Rozhran´ı Set implementuj´ı tˇr´ıdy ArrayList, LinkedList, HashSet, TreeSet pˇredstavuj´ıc´ı jednotliv´e kontejnery. ArrayList je nejpouˇz´ıvanˇejˇs´ım kontejnerem. • Map Rozhran´ı Collection implementuj´ı tˇr´ıdy HashMap a TreeMap. Slouˇz´ı k ukl´ ad´ an´ı uspoˇr´ adan´e dvojice kl´ıˇc-hodnota; s podobn´ ym pˇr´ıstupem jsme se sezn´ amili pˇri pr´ aci s datab´ azemi. Kontejnerov´e tˇr´ıdy maj´ı ˇradu spoleˇcn´ ych vlastnost´ı.
ˇ arkovanou ˇcarou zn´ Obr´ azek 9.2: Hierarchick´ a struktura rozhran´ı Map. C´ azornˇeno rozhran´ı, plnou ˇcarou tˇr´ıdy, kter´e ho implementuj´ı.
9.1
Kontejnery
ˇ Jak jsme jiˇz uvedli, kontejnery v Javˇe pˇredstavuj´ı instance tˇr´ıd implementuj´ıc´ıch rozhran´ı. Rada operac´ı s prvky nad tˇemito tˇr´ıdami je analogick´ a, maj´ı spoleˇcn´eho pˇredka. Typy objekt˚ u ukl´ adan´ ych do kontejner˚ u. Pˇri pr´ aci s kontejnery pouˇz´ıv´ ame dva pˇr´ıstupy. Ukl´ad´ame do nich objekty bud’ objekty obocn´eho typu nebo konkr´etn´ıho pˇredem specifikovan´eho typu. • objekty obecn´eho typu V kontejneru mohou b´ yt uloˇzena data libovoln´eho datov´eho typu. Po uloˇzen´ı do kontejneru objekt ztr´ac´ı informaci o sv´em typu. Pˇred pouˇzit´ım mus´ı b´ yt objekt explicitnˇe pˇretypov´ an. V´ yhodou je vysok´a m´ıra abstrakce a univerz´ alnost, do kontejneru m˚ uˇzeme uloˇzit prakticky cokoliv, nev´ yhodou niˇzˇs´ı pˇrehlednost pr´ ace. Kontejner tedy m˚ uˇze obsahovat jablka i hruˇsky, pˇri pokusu o pˇretypov´ an´ı hruˇsky na jablko m˚ uˇze doj´ıt k v´ yjimce. • objekty konkr´etn´ıho typu Do kontejneru jsou ukl´ ad´ any objekty jednoho konkr´etn´ıho datov´eho typu. Pˇri manipulaci nemus´ı b´ yt pˇretypov´ any, pr´ ace s takov´ ym kontejnerem je bezpeˇcnˇejˇs´ı. V kontejneru si t´ımto pˇr´ıstupem udrˇzujeme poˇr´ adek, obsahuje pouze objekty zadan´eho typu. Tento princip budeme ilustrovat na n´ıˇze uveden´ ych pˇr´ıkladech.
´ DATOVE ´ STRUKTURY KAPITOLA 9. DYNAMICKE ˇ Metody spoleˇ cn´ e pro kontejnery. Rada metod je spoleˇcn´ a pro vˇsechny kontejnery. Kaˇzd´ y z kontejner˚ u m´ a kromˇe nich i metody speci´ aln´ı. V n´ asleduj´ıc´ı tabulce uvedeme seznam nejˇcastˇeji pouˇz´ıvan´ ych metod spoleˇcn´ ych rozhran´ı Collection s jejich struˇcn´ ym popisem. Metoda
Popis
add(Object)
Pˇrid´ an´ı objektu zadan´ eho typu do kontejneru.
clear()
Odstranˇ en´ı vˇsech prvk˚ u z kontejneru.
isEmpty()
Dotaz, zda je kontejner pr´ azdn´ y
remove(Object)
Odstranˇ en´ı objektu z kontejneru.
size()
Velikost kontejneru.
toArray()
Konverze prvk˚ u kontejneru na pole.
Tabulka 9.1: Pˇrehled nejpouˇz´ıvanˇejˇs´ıch metod rozhran´ı Collection.
9.2
Iter´ atory
Iter´ atory pˇredstavuj´ı speci´ aln´ı objekty tˇr´ıdy Iterator, kter´e umoˇzn ˇuj´ı sekvenˇcn´ı proch´ azen´ı obsahem kontejneru. Toto proch´ azen´ı je velmi rychl´e, m˚ uˇze b´ yt jak jednosmˇern´e, tak obousmˇern´e. Pr´ ace s iter´ atory je jednoduch´a, je zaloˇzena na trojici n´ asleduj´ıc´ıch metod hasNext(), next(), remove(). Metoda
Popis
hasNext()
Testuje, zda se v kontejneru vyskytuje dalˇs´ı objekt.
next()
Z´ısk´ an´ı hodnoty dalˇs´ıho objektu.
remove()
Vymaz´ an´ı aktu´ aln´ıho objektu.
Tabulka 9.2: Popis metod tˇr´ıdy Iterator. Podrobnˇeji se s nimi sezn´ am´ıme v dalˇs´ım textu.
9.3
Rozhran´ı List
Rozhran´ı List zahrnuje nejˇcastˇeji pouˇz´ıvanou skupinu kontejnerov´ ych tˇr´ıd. Umoˇzn ˇuje vytvoˇrit a pouˇz´ıvat dynamick´e pole, frontu ˇci z´ asobn´ık. Prvky v tˇechto kontejnerech nemus´ı b´ yt jedineˇcn´e, kontejnery mohou obsahovat i duplicitn´ı poloˇzky. Rozhran´ı je implementov´ ano dvojic´ı tˇr´ıd: • ArrayList Dynamick´e pole, k jednotliv´ ym prvk˚ um lze pˇristupovat pˇr´ımo i prostˇrednictv´ım iter´ atoru. Pˇr´ım´ y pˇr´ıstup je rychlejˇs´ı, sekvenˇcn´ı pˇr´ıstup by proto nemˇel by pˇri pouˇz´ıv´ an k pˇrid´ av´ an´ı, maz´ an´ı, ˇci editov´ an´ı prvk˚ u. ArrayList pˇredstavuje nejpouˇz´ıvanˇejˇs´ı kontejner v Javˇe. • LinkedList Speci´aln´ı typ seznamu optimalizovan´ y pro sekvenˇcn´ı pˇr´ıstup dat. M˚ uˇze b´ yt pouˇz´ıv´ an jako fronta, z´asobn´ık, ˇci oboustrann´ a fronta. Obˇe tˇr´ıdy disponuj´ı ˇradu pokroˇcil´ ych metod pro pr´ aci s daty. V n´ asleduj´ıc´ı kapitole se budeme nejv´ıce vˇenovat kontejneru ArrayList. Problematika dynamick´ ych datov´ ych struktur je velmi rozs´ ahl´ a, z´ ajemce nalezne ˇradu pokroˇcilejˇs´ıch informac´ı v odborn´e literatuˇre.
´ DATOVE ´ STRUKTURY KAPITOLA 9. DYNAMICKE
9.3.1
ArrayList
Kontejner ArrayList pˇredstavuje dynamick´e pole. Kontejner je instanc´ı tˇr´ıdy ArrayList, pracujeme s n´ım jako s jak´ ymkoliv jin´ ym objektem v Javˇe. Jeho obdobou je v jazyce C++ kontejner vector. V Javˇe existuje tak´e, ale nedoporuˇcuje se pˇr´ıliˇs pouˇz´ıvat, v dokumentaci je uv´ adˇen jako obsolete. Chceme -li vytvoˇrit ArrayList, do kter´eho mohou b´ yt ukl´ ad´ ana objekty bez specifikace typu, m´ ame k dispozici nˇekolik konstruktor˚ u. Uved’me dva nejˇcastˇeji pouˇz´ıvan´e ArrayList(); ArrayList(int pocet); Prvn´ı konstruktor vytvoˇr´ı pr´ azdn´ y ArrayList s v´ ychoz´ı kapacitou deset prvk˚ u, druh´ y konstruktor pr´azdn´ y ArrayList se zadanou v´ ychoz´ı kapacitou. Pokud budeme do ArrayListu vkl´ adat data velk´eho rozsahu, m˚ uˇzeme ho na tento krok pˇripravit pouˇzit´ım druh´eho konstruktoru. Chceme -li vytvoˇrit ArrayList, do kter´eho maj´ı b´ yt ukl´ ad´ ana objekty konkr´etn´ıho datov´eho typu, lze konstruktory zapsat ve tvaru ArrayList(); ArrayList(int pocet); Pˇ rehled z´ akladn´ıch metod tˇ r´ıdy ArrayList. V n´ asleduj´ıc´ı tabulce uvedeme pˇrehled z´ akladn´ıch metod pro pr´ aci s ArrayListem. Metoda
Popis
add(index, Object o)
Na specifikovanou pozici pˇrid´ a zadan´ y prvek.
get(int index)
Vrac´ı hodnotu prvku se zadanou pozic´ı v seznamu.
remove(int index)
Prvku se zadanou pozic´ı odstran´ı ze seznamu.
set(int index, Object o)
Prvku se zadanou pozic´ı v seznamu nastav´ı zadanou hodnotu.
Tabulka 9.3: Pˇrehled nejpouˇz´ıvanˇejˇs´ıch metod pro pr´ aci s ArrayListem. Nev´ yhodu ArrayListu pˇredstavuje pomalost nˇekter´ ych operac´ı, zejm´ena hled´ an´ı prostˇrednictv´ım metody get(). proto jsou pouˇz´ıv´ any efektivnˇejˇs´ı kontejnery, napˇr. HashMap. Pˇ r´ıklad 1. Implementace nˇekolika operac´ı ilustruj´ıc´ıch pr´ aci s ArrayListem: vytvoˇren´ı seznamu, jeho vytisknut´ı nˇekolika metodami. Editace a odstranˇen´ı poloˇzky. ArrayList bude pˇredstavovat seznam pˇr´ıjmen´ı. Pro uloˇzen´ı pˇr´ıjmen´ı pouˇzijeme datov´ y typ String. Vytvoˇr´ıme pr´ azdn´ y ArrayList typu String, s jehoˇz instanc´ı budeme pracovat. ArrayList <String> seznam; seznam=new ArrayList<String>(); V dalˇs´ım kroku prostˇrednictv´ım metody add() do ArrayListu pˇrid´ ame u ´daje. seznam.add("Novak"); seznam.add("Vopicka"); seznam.add("Vonasek"); seznam.add("Hujer"); seznam.add("Hlinik");
´ DATOVE ´ STRUKTURY KAPITOLA 9. DYNAMICKE Vytisknut´ı obsahu ArrayListu provedeme tˇremi metodami. Prvn´ı, s vyuˇzit´ım instance tˇr´ıdy Iterator, lze zapsat takto: Iterator i = seznam.iterator(); while(i.hasNext()) { System.out.println(i.next()); } Druh´ a vyuˇz´ıv´ a metody get(). Poˇcet prvk˚ u ArrayListu urˇc´ıme metodou size() a pomoc´ı cyklu for je postupnˇe proch´ az´ıme. for (int i=0;i<seznam.size();i++) { System.out.println(seznam.get(i)); } Pˇridejme na druhou pozici novou poloˇzku“Plha”. Pouˇzijeme k tomu pˇret´ıˇzenou metodu seznam.add(1,"Plha"). V´ ysledek vypad´ a takto: Novak Plha Vopicka Vonasek Hujer Hlinik Posledn´ı poloˇzku ArrayListu budeme editovat, zmˇen´ıme pˇr´ıjmen´ı z “Hlinik” na “Hlinikova”; posledn´ı poloˇzka Arraylistu m´ a index [seznam.size()-1]. seznam.set(seznam.size()-1,"Hlinikova"); Dalˇs´ı uk´azku pr´ ace s ArrayListem nalezneme v kapitole 10.1.9.2.
9.4
Rozhran´ı Set
Rozhran´ı Set implementuje stejn´e rozhran´ı jako Collection. Na rozd´ıl od Collection nemohou kontejnery obsahovat duplicitn´ı poloˇzky. Rozhran´ı je implementov´ ano dvojic´ı tˇr´ıd: • HashSet Setˇr´ıdˇen´ y kontejner vyuˇz´ıvaj´ıc´ı techniku haˇsov´ an´ı. Kaˇzd´ y objekt mus´ı m´ıt pˇriˇrazenu metodou hashCode() hodnotu haˇsovac´ı funkce. Hodnotu haˇsovac´ı funkce pouˇz´ıv´ a pro vyhled´ av´ an´ı prvku. V tomto kontejneru jsou jednotliv´e poloˇzky nesetˇr´ıdˇen´e. Princip haˇsov´ an´ı patˇr´ı mezi pokroˇcil´e techniky, nebudeme se j´ım podrobnˇeji zab´ yvat. • TreeSet Setˇr´ıdˇen´ y kontejner vyuˇz´ıvaj´ıc´ı operace se stromem. Poloˇzky v kontejneru jsou setˇr´ıdˇeny. Na rozd´ıl od rozhran´ı list komponenty HashSet a TreeSet nedisponuj´ı ˇz´ adn´ ymi nov´ ymi n´ astroji umoˇzn ˇuj´ı pouze sekvenˇcn´ı pˇr´ıstup prostˇrednictv´ım iter´ atoru. Neexistuje u nich metoda get(), pomoc´ı kter´e lze pˇristoupit pˇr´ımo ke konkr´etn´ımu prvku.
´ DATOVE ´ STRUKTURY KAPITOLA 9. DYNAMICKE
9.4.1
TreeSet
Kontejner se pouˇz´ıv´ a pro uchov´ av´ an´ı setˇr´ıdˇen´ ych dat neobsahuj´ıc´ıch duplicitn´ı prvky. Pro vytvoˇren´ı instance tˇr´ıdy TreeSet je k dispozici nˇekolik konstruktor˚ u, uvedeme pouze dva nejˇcastˇeji pouˇz´ıvan´e: TreeSet(); TreeSet(); Jejich v´ yznam je podobn´ y jako v pˇr´ıpadˇe ArrayListu, vytv´ aˇrej´ı pr´ azdn´ y TreeSet libovoln´eho nebo konkr´etn´ıho datov´eho typu. Princip fungov´ an´ı kontejneru TreeSet uk´ aˇzeme na n´ asleduj´ıc´ım pˇr´ıkladu. Pˇ r´ıklad 2. Vytvoˇren´ı seznamu jmen a jejich setˇr´ıdˇen´ı prostˇrednictv´ım kontejneru TreeSet. TreeSet <String> t; t=new TreeSet<String>(); t.add("Novak"); t.add("Vopicka"); t.add("Vonasek"); t.add("Hujer"); t.add("Hlinik"); Vyp´ıˇseme -li prostˇrednictv´ım iter´ atoru obsah tohoto kontejneru, vid´ıme, ˇze je automaticky setˇr´ıdˇen. Iterator it2 = t.iterator(); while(it2.hasNext()) { System.out.println(it2.next()); } V´ ysledek vypad´ a takto: Hlinikova Hlinik Hujer Novak Vonasek Vopicka
9.5
Rozhran´ı Map
Rozhran´ı Map umoˇzn ˇuje uchov´ avat uspoˇr´ adan´e dvojice kl´ıˇc-hodnota, slouˇz´ı k operac´ım s hodnotami na z´ akladˇe jejich kl´ıˇc˚ u. Toto tvrzen´ı lze zobecnit: v kontejnerech Map vyhled´ av´ ame objekty na z´ akladˇe hodnot jin´ ych objekt˚ u. Takov´e kontejnery b´ yvaj´ı nˇekdy oznaˇcov´ any jako kontejnery sdruˇzovac´ı. V souˇcasn´e dobˇe jsou velmi popul´ arn´ı. Hodnoty kl´ıˇce nesmˇej´ı b´ yt duplicitn´ı, kaˇzd´ y z kl´ıˇc˚ u mus´ı m´ıt unik´ atn´ı hodnotu. Rozhran´ı je implementov´ ano dvojic´ı tˇr´ıd:
´ DATOVE ´ STRUKTURY KAPITOLA 9. DYNAMICKE • HashMap Tento kontejner vyuˇz´ıv´ a haˇsovac´ı tabulku. V´ yhodou tohoto kontejneru je velmi rychl´e vyhled´av´an´ı, v ˇr´ adech rychlejˇs´ı neˇz u ArrayListu. Parametry haˇsov´ an´ı ovlivˇ nuj´ıc´ı v´ ykon kontejneru lze nastavit v konstruktoru. • TreeMap TreeMap vyuˇz´ıv´ a speci´ aln´ı strukturu naz´ yvanou ˇcerveno-ˇcern´ y strom. Uspoˇr´ adan´e dvojice kl´ıˇc-hodnota jsou setˇr´ıdˇeny na z´ akladˇe kl´ıˇce. Rozhran´ı Entry. Pˇri pr´ aci s mapami je ˇcasto pouˇz´ıv´ ano rozhran´ı Entry. Umoˇzn ˇuje manipulace s uspoˇr´adan´ ymi dvojicemi kl´ıˇc-hodnota. Implementuje tyto d˚ uleˇzit´e metody: Metoda
Popis
getKey()
Vrac´ı aktu´ aln´ı kl´ıˇ c
getValue()
Vrac´ı aktu´ aln´ı hodnotu
Tabulka 9.4: Metody rozhran´ı Entry.
9.5.1
TreeMap
Na rozd´ıl od HashMap jsou dvojice kl´ıˇc-hodnota setˇr´ıdˇeny, a to vzestupnˇe. Pokud poˇzadujeme jin´ y typ setˇr´ıdˇen´ı, je nutno implementovat rozhran´ı Comparable.2 K dispozici je nˇekolik konstruktor˚ u, uved’me dva nejjednoduˇsˇs´ı. TreeMap(); TreeMap(pole1,pole2) Prvn´ı konstruktor vytvoˇr´ı pr´ azdn´ y TreeMap, druh´ y konstruktor TreeMap takov´ y, ˇze pole1 tvoˇr´ı kl´ıˇce a pole2 hodnoty. Obˇe pole mus´ı m´ıt stejnou d´elku. Pˇrehled nejd˚ uleˇzitˇejˇs´ıch metod pro pr´ aci s kontejnerem TreeMap nalezneme v n´ asleduj´ıc´ı tabulce. Metoda
Popis
ContainsKey(Object key)
Vrac´ı hodnotu true, pokud TreeMap obsahuje kl´ıˇ c key.
ContainsValue(Object value)
Vrac´ı hodnotu true, pokud TreeMap obsahuje hodnotu ovalue.
get(Object key)
Vr´ at´ı hodnotu odpov´ıdaj´ıc´ı kl´ıˇ ci.
put(Object key, Object value)
Pˇrid´ a dvojici kl´ıˇ c-hodnota.
remove(Object key)
Odtran´ı z TreeMap kl´ıˇ c a jemu odpov´ıdaj´ıc´ı hodnotu.
entrySet()
Vrac´ı obsah TreeMap ve formˇ e Setu.
Tabulka 9.5: Pˇrehled metod pro pr´ aci s kontejnerem TreeMap. Pr´ aci s kontejner TreeMap neumoˇzn ˇuje pˇr´ıstup k prvk˚ um prostˇrednictv´ım iter´ atoru. Pokud vˇsak chceme pˇri pr´ aci s kontejnerem TreeMap pouˇz´ıt iter´ atory, m˚ uˇzeme si pomoci menˇs´ı oklikou. Vytvoˇr´ıme Set, obsah TreeMap pˇrevedeme metodou entrySet() do Setu, kter´ y jiˇz operace s iter´ atory podporuje. Vlastnosti TreeMap budeme ilustrovat na jednoduch´em pˇr´ıkladu. 2 Problematikou
rozhran´ı Comparable se zab´ yvat nebudeme, z´ ajemce ji najde v odborn´ e literatuˇre.
´ DATOVE ´ STRUKTURY KAPITOLA 9. DYNAMICKE Pˇ r´ıklad 3. Vytvoˇren´ı seznamu telefonn´ıch ˇc´ısel. Kl´ıˇc bude pˇredstavovat pˇr´ıjmen´ı, hodnotu telefonn´ı ˇc´ıslo. Vytvoˇren´ı kontejneru TreeMap provedeme pomoc´ı TreeMap tels; tels=new TreeMap(); Napln´ıme ho uspoˇr´ adan´ ymi dvojicemi kl´ıˇc-hodnota. tels.put("Vopicka","602123456"); tels.put("Vonasek","603111222" ); tels.put("Hujer", "605987654"); tels.put("Hlinik","608500500"); Jinou moˇznost naplnˇen´ı TreeMap poskytuje druh´ y konstruktor. Vytvoˇr´ıme dvojic´ı pol´ı String [] jmena = {"Vopicka", "Vonasek", "Hujer", "Hlinik"}; String [] telefony = {"602123456", "603111222", "605987654", "608500500"}; TreeMap vytvoˇr´ıme pomoc´ı TreeMap tels; tels=new TreeMap(jmena, telefony); Obsah TreeMap pˇrevedeme do Setu. Set s=tels.entrySet(); Vyps´ an´ı obsahu TreeMap prostˇrednictv´ım iter´ atoru. Vytvoˇr´ıme referenˇcn´ı promˇennou rozhran´ı Entry a pomoc´ı metod getKey() a getValue() z´ısk´ ame aktu´ aln´ı kl´ıˇc a hodnotu. Iterator it2 = s.iterator(); while(it2.hasNext()) { Map.Entry e=(Map.Entry)it2.next(); Object jm = e.getKey(); Object te = e.getValue(); System.out.println(jm); System.out.println(te); } Chceme -li nal´ezt hodnotu odpov´ıdaj´ıc´ı kl´ıˇci, pouˇzijeme metodu get(). System.out.println(tels.get("Vopicka"));
Kapitola 10
Java, grafick´ e uˇ zivatelsk´ e rozhran´ı Programovac´ı jazyk Java obsahuje disponuje grafick´ ym uˇzivatelsk´ ym rozhran´ım (Graphic User Interface) nez´avisl´ ym na zaˇr´ızen´ı. Grafick´e operace poskytuj´ı stejn´e v´ ysledky bez ohledu na typ poˇc´ıtaˇce ˇci pouˇz´ıvan´ y operaˇcn´ı syst´em. Tato vlastnost je v Javˇe velmi d˚ uleˇzit´a, uplatˇ nuje se pˇri tvorbˇe aplikac´ı, jejichˇz vzhled je pod r˚ uzn´ ymi operaˇcn´ımi syst´emy (velmi) podobn´ y. Pro v´ yvoj GUI aplikac´ı nen´ı nutn´e m´ıt k dispozici ˇz´adn´e v´ yvojov´e prostˇred´ı, vizu´ aln´ı komponenty lze vytv´aˇret pomˇernˇe jednoduˇse z´apisem zdrojov´eho k´odu. Pr´ace ve v´ yvojov´em prostˇred´ı RAD je pˇr´ıjemnˇejˇs´ı a pohodlnˇejˇs´ı, umoˇzn ˇuje vytvoˇrit grafick´e uˇzivatelsk´e rozhran´ı bez nutnosti z´apisu k´ odu pouze metodou drag and drop. V t´eto kapitole se budeme zab´ yvat prvn´ı variantou. Grafick´ e uˇ zivatelsk´ e rozhran´ı. V naˇsich aplikac´ıch m˚ uˇzeme pouˇz´ıvat ˇradu vizu´aln´ıch komponent: formul´aˇre, tlaˇc´ıtka, pˇrep´ınaˇce, dialogy, grafick´e komponenty, multimedi´aln´ı komponenty, tiskov´e komponenty. Tyto komponenty tvoˇr´ı rozhran´ı aplikace, umoˇzn ˇ uj´ı vz´ajemnou komunikaci mezi uˇzivatelem a aplikac´ı (zad´av´an´ı dat nebo zn´ azorˇ nov´ an´ı v´ ysledk˚ u r˚ uzn´ ych v´ ypoˇcetn´ıch ˇci grafick´ ych operac´ı). Popsan´ y pˇr´ıstup je pro Javu pˇrirozenˇejˇs´ı, pr´ ace s form´ atovan´ ym vstupem ˇci v konzoli nen´ı na rozd´ıl od C/C++ pro Javu typick´a. V´ yhodou pr´ace s GUI je snadnˇejˇs´ı ovladatelnost, pˇrehlednost, n´azornost. Pˇri n´avrhu grafick´eho uˇzivatelsk´eho rozhran´ı je nutno zohlednit, ˇze aplikace se nem´a pˇrizp˚ usobovat uˇzivateli a nikoliv uˇzivatel aplikaci. Typy grafick´ ych rozhran´ı v Javˇ e. Java disponuje dvˇema grafick´ ymi rozhran´ımi. Starˇs´ı z nich, AWT (Abstract Windows Toolkit), se jiˇz pouˇz´ıv´ a jen v´ yjimeˇcnˇe (applety). Jeho nev´ yhodou byla znaˇcn´a n´aroˇcnost na hardware a nepˇr´ıliˇs pˇekn´ y vzhled (subjektivn´ı, leˇc rozˇs´ıˇren´e tvrzen´ı), v´ yhodou podpora prakticky vˇsech browser˚ u, AWT rozhran´ı je vl´ aknovˇe zabezpeˇcen´e. Aplikace pˇrej´ımala vzhled OS, na kter´em bˇeˇzela. Toto rozhran´ı bylo nahrazeno rozhran´ım JFC (Java Foundation Classes) obsahuj´ıc´ım jak vizu´aln´ı, tak nevizu´aln´ı komponenty. Nevizu´ aln´ı komponenty naz´ yv´ame Java Beans (k´avov´e boby), vizu´aln´ı komponenty pˇredstavuj´ı grafick´e rozhran´ı Swing. Swing je bohatˇs´ı na komponenty, vych´az´ı vˇsak z AWT. Vyuˇz´ıv´ a stejn´e ud´alosti, je postaven na podobn´ ych komponent´ach, pr´ace s obˇema rozhran´ımi je v´ıce-m´enˇe analogick´ a. Rozhran´ı Swing je rychlejˇs´ı, nev´ yhodou je fakt, ˇze ho neum´ı zobrazit korektnˇe vˇsechny browsery, je vl´aknovˇe nezabezpeˇcen´e. Vzhled aplikac´ı a jejich komponent bˇeˇz´ıc´ıch nad rozhran´ım Swing m˚ uˇze b´ yt mˇenˇen, aplikace nemus´ı pˇrej´ımat vzhled OS. N´ azvy tˇ r´ıd. N´azvy tˇr´ıd v knihovnˇe AWT vych´azej´ı ze standardizovan´ ych jmen komponent (Button, Table, Frame, ...), n´ azvy tˇr´ıd v rozhran´ı Swing se odliˇsuj´ı pˇrid´an´ım p´ısmene J pˇred n´azev komponenty (JButton, JTable, JFrame,...). V t´eto kapitole se budeme zab´ yvat v´ yhradnˇe popisem rozhran´ı Swing.1 V ˇcesk´em jazyce 1 Obecnˇ e je vˇsak rozhran´ı Swing pomˇ ernˇ e pomal´ e. Jsou proto pouˇ z´ıv´ ana i jin´ a grafick´ a rozhran´ı, napˇr. SWT (v prostˇred´ı Eclipse).
95
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E existuje velmi m´ alo materi´ al˚ u zab´ yvaj´ıc´ıch se touto problematikou, podrobn´e informace o rozhran´ı Swing lze nal´ezt na str´ ank´ ach spoleˇcnosti Sun: http://java.sun.com/docs/books/tutorial/uiswing/index.html Ud´ alostmi ˇ r´ızen´ e programov´ an´ı. Tento zp˚ usob programov´ an´ı je znaˇcnˇe odliˇsn´ y od pˇr´ıstupu, kter´ y jsme doposud pouˇz´ıvali. Program je tvoˇren ˇradou r˚ uzn´ ych grafick´ ych komponent, kter´e jsou za jeho bˇehu zobrazov´ any. Ud´ alost (event) vznik´ a ˇcinnost´ı uˇzivatele, programu nebo OS (stisk, posun myˇsi, kl´ avesy, maximalizace, minimalizace, zavˇren´ı okna, zmˇena rozmˇer˚ u okna, stisk tlaˇc´ıtka, pˇrekreslen´ı obrazovky, ...). Kaˇzd´ a z vizu´aln´ıch komponent m´ a vlastn´ı ud´ alosti, na kter´e m˚ uˇzeme reagovat, tzv. je obslouˇzit. Obsluˇzn´ y k´ od je ps´ an do metod, kter´e naz´ yv´ ame handlery. Tento zp˚ usob programov´ an´ı naz´ yv´ ame ud´ alostmi ˇr´ızen´ ym programov´ an´ım. Vytvoˇren´ı aplikace zpravidla pˇredstavuje nˇekolik ˇcinnost´ı • Implementace v´ ykonn´e ˇc´ asti programu. • Navrˇzen´ı a vytvoˇren´ı grafick´eho rozhran´ı. • Zajiˇstˇen´ı moˇznosti korektn´ıho ukonˇcen´ı programu. • Definice ud´ alosti, kter´e maj´ı b´ yt v programu obslouˇzeny, • Z´apis k´ odu pro obsluhu ud´ alost´ı formou handler˚ u. Upozornˇeme, ˇze n´ avrh grafick´eho rozhran´ı by mˇel b´ yt vˇzdy oddˇelen od v´ ykonn´e ˇc´ asti programu. Tuto z´asadu budeme jeˇstˇe nˇekolikr´ at opakovat.
10.1
Z´ akladn´ı komponenty a ud´ alosti
V t´eto kapitole se sezn´ am´ıme s nˇekter´ ymi ˇcasto pouˇz´ıvan´ ymi vizu´ aln´ımi komponentami knihovny Swing a ud´ alostmi s nimi spojen´ ymi. Popis vˇsech komponent by vydal na samostatnou knihu, nebudeme ho proto uv´ adˇet. Nejprve je nutno importovat bal´ıˇcek javax.swing.*.
10.1.1
Rozdˇ elen´ı komponent
V Javˇe je k dispozici velk´e mnoˇzstv´ı r˚ uzn´ ych typ˚ u grafick´ ych komponent. Lze je rozdˇelit do nˇekolika skupin, uved’me nejpouˇz´ıvanˇejˇs´ı ˇclenˇen´ı na z´ akladˇe hierarchick´e struktury komponent: • Top-level komponenty • Kontejnerov´e komponenty • Z´akladn´ı komponenty • Needitovateln´e informaˇcn´ı komponenty • Interaktivn´ı komponenty V n´ asleduj´ıc´ım pˇrehledu uvedeme nejd˚ uleˇzitˇejˇs´ı z´ astupce jednotliv´ ych skupin komponent.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.2: Uk´ azka komponent JPanel a JScrollPane. 10.1.1.1
Top-level komponenty
Tyto komponenty jsou v hierarchii komponent na nejvyˇsˇs´ım stupni. Kaˇzd´ a aplikace mus´ı obsahovat alespoˇ n jednu top-level komponentu. M˚ uˇzeme si je pˇredstavit jako komponenty, na kter´e mohou b´ yt umist’ov´ any jin´e komponenty (tj. komponenty podkladov´e) nebo na nˇe naopak jiˇz ˇz´ adnou dalˇs´ı komponentu um´ıstit nelze.
Obr´ azek 10.1: Uk´ azka komponent JFrame a JDialog. Mezi nejˇcastˇeji pouˇz´ıvan´e top-level komponenty patˇr´ı JFrame (formul´ aˇr) a JDialog. 10.1.1.2
Kontejnerov´ e komponenty
Tyto komponenty se nach´ azej´ı na niˇzˇs´ı hierarchick´e u ´ rovni neˇz top-level komponenty. Slouˇz´ı k seskupov´an´ı komponent, mohou na nˇe b´ yt umist’ov´ any jin´e komponenty stejn´e nebo niˇzˇs´ı hierarchick´e u ´rovnˇe. Kontejnerov´e komponenty b´ yvaj´ı zpravidla um´ıstˇeny na top-level komponent´ ach. Do t´eto skupiny patˇr´ı: JPanel, JScrollPane (panel s posuvn´ıky pro zobrazov´ an´ı obr´ azk˚ u), JTabbedPane (panel se z´ aloˇzkami) ˇci JToolbar (panel n´ astroj˚ u).
Obr´ azek 10.3: Uk´ azka komponent JTabbedPane a JToolbar.
10.1.1.3
Z´ akladn´ı komponenty
Tyto komponenty slouˇz´ı pro zajiˇstˇen´ı komunikace mezi uˇzivatelem a aplikac´ı. Vyskytuj´ı se prakticky v kaˇzd´e aplikaci, napˇr´ıˇc programovac´ımi jazyky a operaˇcn´ımi syst´emy.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.4: Uk´ azka komponent JButton, JCheckBox, JRadioButton, JComboBox. Do t´eto skupiny patˇr´ı: JButton (tlaˇc´ıtko), JCheckBox (zaˇskrt´ avac´ı pole), JRadioButton (pˇrep´ınac´ı tlaˇc´ıtko), JComboBox (rozbalovac´ı seznam), JList (seznam), JMenu, JTextField (textov´e pole), JSpinner (zad´av´an´ı ˇc´ıseln´ ych u ´ daj˚ u).
Obr´ azek 10.5: Uk´ azka komponent JList a JMenu, JTextField, JSpinner.
10.1.1.4
Needitovateln´ e informaˇ cn´ı komponenty
Nˇekdy b´ yvaj´ı naz´ yv´ any jako informaˇcn´ı komponenty. Jejich obsah nem˚ uˇze b´ yt uˇzivatelem mˇenˇen. Do t´eto skupiny lze zaˇradil JLabel (popis) ˇci JProgressBar (zobrazen´ı pr˚ ubˇehu bˇeˇz´ıc´ıho procesu).
Obr´ azek 10.6: Uk´ azka komponent JLabel a JProgressBar.
10.1.1.5
Interaktivn´ı komponenty
Jedn´ a se o komponenty pˇredstavovan´e zpravidla standardn´ımi dialogy umoˇzn ˇuj´ıc´ımi prov´ adˇet ˇcasto opakovan´e ˇcinnosti: v´ ybˇer souboru, volba barvy, hled´ an´ı souboru. Mohou tak´e zobrazovat v´ ysledky v´ ypoˇct˚ u ve form´ atovan´em tvaru ve formˇe tabulek ˇci strom˚ u.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.7: Uk´ azka komponent JFileChooser a JColorChooser. Do t´eto skupiny patˇr´ı JFileChooser (v´ ybˇer souboru), JColorChooser (v´ ybˇer barvy), JTree (Strom), JTable (Tabulka).
Obr´ azek 10.8: Uk´ azka komponent JTable a JTree.
10.1.2
Formul´ aˇ re
Patˇr´ı do skupiny top-level komponent. Jelikoˇz se jedn´ a o nejˇcastˇejˇs´ı top-level komponentu, u ´vodn´ı v´ yklad budeme smˇeˇrovat pr´ avˇe na formul´ aˇre. Pro pr´ aci s formul´ aˇri je pouˇz´ıv´ ana tˇr´ıda JFrame. V praxi je v´ yhodnˇejˇs´ı pracovat se tˇr´ıdou odvozenou od tˇr´ıdy JFrame, ve kter´e m˚ uˇzeme s jednotliv´ ymi komponentami a jejich parametry efektivnˇeji manipulovat. Tento postup umoˇzn ˇuje oddˇelit od sebe grafick´e a aplikaˇcn´ı rozhran´ı aplikace, v praxi je velmi ˇcasto pouˇz´ıv´ an. Nejprve se pokus´ıme vytvoˇrit formul´ aˇr a zobrazit ho na obrazovce; k tomuto u ´ˇcely pouˇzijeme tˇr´ıdu Okno. import javax.swing.*; public class Okno extends JFrame{ public Okno() {} } Ve tˇr´ıdˇe Komponenty budeme pracovat s instanc´ı tˇr´ıdy Okno. Instanci nestaˇc´ı pouze vytvoˇrit, je nutn´e za pouˇzit´ı metody setVisble(boolean status) nastavit jej´ı zobrazen´ı. public class Komponenty { public static void main (String [] args) { Okno o=new Okno(); o.setVisible(true); }
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Z takto vznikl´eho okna bude vidˇet pouze jeho titulek, nen´ı v nˇem vˇsak uvedena ˇz´ adn´ a informace, coˇz nen´ı pro praktickou pr´ aci vhodn´e.
Obr´ azek 10.9: Uk´ azka formul´ aˇre bez nastaven´ych rozmˇer˚ u. Proto prostˇrednictv´ım metody setDimension(int width, int height) nastav´ıme formul´ aˇri ˇs´ıˇrku a v´ yˇsku, hodnoty jsou uv´ adˇeny v pixelech a prostˇrednictv´ım metody setTitle(String title) zad´ ame titulek. public class Komponenty { public static void main (String [] args) { Okno o=new Okno(); o.setSize(640, 480); o.setTitle("Moje okno"); o.setVisible(true); } V´ ysledek vypad´ a takto
Obr´ azek 10.10: Uk´ azka formul´ aˇre s nastaven´ymi rozmˇery. Okno vˇsak m´ a jeden nedostatek, pˇri jeho vypnut´ı prostˇrednictv´ım kˇr´ıˇzku sice zmiz´ı, aplikace vˇsak bˇeˇz´ı d´ale. Do programu mus´ıme zaˇclenit k´ od zajiˇst’uj´ıc´ı ukonˇcen´ı programu pˇri zavˇren´ı okna. Slouˇz´ı k tomu metoda setDefaultCloseOperation(int o), kter´ a by mˇela b´ yt vol´ ana ihned po vytvoˇren´ı instance. Oknu d´ale nastav´ıme metodou setLocation(int x, int y) polohu na obrazovce. public static void main (String [] args) { Okno o=new Okno(); o.setSize(640, 480); o.setTitle("Moje okno"); o.setLocation(100,100); o.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); o.setVisible(true); }
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Vlastnosti komponent. Pro z´ısk´ an´ı vlastnost´ı komponent ˇci jejich nastaven´ı pouˇz´ıv´ ame dle v´ yˇse uveden´ ych konvenc´ı gettery a settery. Jejich n´ azvy jsou v tomto pˇr´ıpadˇe tvoˇreny kombinac´ı vlastnosti, napˇr.: Size, Title, Name, Font, Visible, Location a oznaˇcen´ı set nebo get. Gettery jsou bezparametrick´e, settery obsahuj´ı seznam parametr˚ u, kter´e je potˇreba komponentˇe nastavit. Vzniknou tak metody getSize(), getTitle(), getName(), getFont(), getLocation() ..., ˇci setSize(), setTitle(), setName(), setFont(), setLocation(). Upozornˇeme, ˇze veˇsker´ a nastaven´ı komponenty je nutn´e prov´est pˇred t´ım, neˇz bude komponenta zobrazena. Zamˇ eˇ ren´ı komponenty. D˚ uleˇzitou vlastnost´ı komponenty je jej´ı zamˇeˇren´ı, tzv. fokus. V kaˇzd´em okamˇziku je jedna z komponent nach´ azej´ıc´ıch se na formul´ aˇri aktivn´ı, ˇr´ık´ ame o n´ı, ˇze je zamˇeˇren´ a (tj. m´ a fokus). Tento stav se projev´ı grafick´ ym zv´ yraznˇen´ım komponenty. Zamˇeˇren´ a komponenta m˚ uˇze reagovat i na vstup z kl´ avesnice (napˇr. kl´ avesov´e zkratky).
Obr´ azek 10.11: Uk´ azka zamˇeˇren´ı komponenty, tlaˇc´ıtko OK. 10.1.2.1
Nastaven´ı vzhledu komponent
Kaˇzd´emu formul´ aˇri ale i ostatn´ım ostatn´ım komponent´ am na nˇem um´ıstˇen´ ym, m˚ uˇzeme nastavit r˚ uzn´ y vzhled, tzv. look and feel. Komponenty v Javˇe jsou skinovateln´e. Existuje velk´e mnoˇzstv´ı r˚ uzn´ ych skin˚ u, kter´e jsou volnˇe dostupn´e na Internetu. Velikosti, tvary, barvy jednotliv´ ych komponent mohou b´ yt r˚ uzn´e. Pro spr´avu vzhled˚ u pouˇz´ıv´ ame statickou tˇr´ıdu UIManager, kterou je nutno importovat. Nejˇcastˇeji pouˇz´ıvanou metodou je metoda setLookAndFeel(), kter´e umoˇzn ˇ uj´ıc´ı nastavit vzhled aplikace. K´ od je obalen v sekvenci try-catch, jedn´ a se o synchronn´ı v´ yjimku. try { UIManager.setLookAndFeel(UIManager. getSystemLookAndFeelClassName()); } catch (Exception e) { // handle exception } K dispozici jsou dvˇe z´ akladn´ı varianty: • getCrossPlatformLookAndFeelClassName():Aplikace bude m´ıt stejn´ y vzhled nez´ avisle na operaˇcn´ım syst´emu, na kter´em bˇeˇz´ı; tento vzhled naz´ yv´ ame MetalLookAndFeel. Jedn´ a se o v´ ychoz´ı variantu, kter´a bude pouˇzita, pokud uˇzivatel neprovede ˇz´ adn´e nastaven´ı. • getSystemLookAndFeelClassName(): Aplikace bude m´ıt vzhled obvykl´ y v dan´em operaˇcn´ım syst´emu. Na platformˇe Windows WindowsLookAndFeel a na platformˇe Linux/Unix MotifLookAndFeel. Ve vˇetˇsinˇe pˇr´ıpad˚ u je vhodnˇejˇs´ı pouˇz´ıt tuto variantu. Nastaven´ı look and feel metodou setLookAndFeel mus´ı b´ yt provedeno pˇred zobrazen´ım formul´ aˇre. Existuj´ı i metody, s jejichˇz pouˇzit´ım je moˇzno mˇenit vzhled aplikace ”za bˇehu”. Dalˇs´ı podrobnosti o moˇznostech nastavov´ an´ı vzhledu komponent lze nal´ezt v dokumentaci na http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel/plaf.html.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Uk´azky vzhledu t´eˇze aplikace s v´ yˇse uveden´ ymi looks and feels jsou zobrazeny na n´ asleduj´ıc´ım obr´ azku.
Obr´ azek 10.12: Uk´ azka Look and Feel: MetalLookAndFeel, MotifLookAndFeel, WindowsLookAndFeel. 10.1.2.2
Nastavov´ an´ı parametr˚ u grafick´ eho rozhran´ı v konstruktoru jin´ e tˇ r´ıdy
Pˇr´ıstup, pˇri kter´em jsou parametry grafick´eho rozhran´ı nastavov´ any v metodˇe main() tˇr´ıdy, ve kter´e byla ˇ instance s grafick´ ym rozhran´ım vytvoˇrena, nen´ı vhodn´ y. Casto potˇrebujeme vytvoˇrit nˇekolik instanc´ı t´eˇze tˇr´ıdy, z nichˇz kaˇzd´ a bude disponovat grafick´ ym rozhran´ım se stejn´ ymi parametry. Z tohoto d˚ uvodu je vhodn´e prov´est nastaven´ı vlastnost´ı instance v konstruktoru tˇr´ıdy. import javax.swing.UIManager; public class Komponenty { public Komponenty() { Okno o=new Okno(); o.setSize(640, 480); o.setTitle("Moje okno"); o.setLocation(100,100); o.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); o.setVisible(true); } public static void main (String [] args) { try { UIManager.setLookAndFeel(UIManager. getSystemLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } new Komponenty(); } Nastaven´ı look and feelu je provedeno v metodˇe main(). Pokud se nepovede, zpravidla pokraˇcujeme bˇeˇzn´ ym zp˚ usobem, tj. vytvoˇr´ıme grafick´e rozhran´ı a sm´ıˇr´ıme se s t´ım, ˇze nevypad´ a tak, jak poˇzadujeme. 10.1.2.3
Nastavov´ an´ı parametr˚ u grafick´ eho rozhran´ı v konstruktoru t´ eˇ ze tˇ r´ıdy
Tento pˇr´ıstup umoˇzn ˇuje l´epe oddˇelit tˇr´ıdu vytv´ aˇrej´ıc´ı okno od tˇr´ıdy, kter´ a bude toto okno vyuˇz´ıvat. Vytvoˇren´ı formul´ aˇre je provedeme v konstruktoru tˇr´ıdy Okno. Pˇri pouˇzit´ı implicitn´ıho konstruktoru budou pˇri vytvoˇren´ı nov´e instance tˇr´ıdy Okno vˇzdy vytvoˇreny formul´ aˇre stejn´ ych vlastnost´ı.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E import javax.swing.UIManager; public class Okno extends JFrame { public Okno() { this.setSize(640, 480); this.setTitle("Moje okno"); this.setLocation(100,100); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } public static void main (String [] args) { try { UIManager.setLookAndFeel(UIManager. getSystemLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } new Okno(); } Pokud bychom chtˇeli velikosti oken nastavit pˇri vytv´ aˇren´ı instance, bylo by nutno tvorbu formul´ aˇre prov´est v explicitn´ım konstruktoru, jehoˇz form´ aln´ı parametry pˇredstavuj´ı parametry formul´ aˇri nastavovan´e. public Okno(int sirka, int vyska) { this.setSize(sirka, vyska); this.setTitle("Moje okno"); this.setLocation(100,100); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } Ikona programu. Na formul´ aˇri je moˇzno zobrazit i ikonu programu pˇredstavovanou obr´ azkem, a to v nˇekter´em z n´ asleduj´ıc´ıch form´ at˚ u: JPG, GIF,PNG. Lze si tak vytv´ aˇret i ikony vlastn´ı a nespol´ehat se jen na v´ ychoz´ı. Standardn´ı velikost ikony je 16x16 pixel˚ u. K tˇemto operac´ım slouˇz´ı tˇr´ıda ImageIcon. V konstruktoru instance tˇr´ıdy zad´ ame cestu k obr´ azku a metodou setIconImage(Image i) ho nastav´ıme jako ikonu ImageIcon i=new ImageIcon("C:\\Tomas\\ikona.png");
this.setIconImage(i.getImage());
V´ ysledek je zn´ azornˇen na obr. 10.3. Vytvoˇ ren´ı druh´ eho frame. V aplikace je moˇzn´e vytvoˇrit i dalˇs´ı frame. Nen´ı to typick´e, aplikace by mˇela m´ıt pouze jeden frame a napˇr. okna zobrazovat formou dialogu. Takto vznikl´emu framu je nutn´e tak´e oˇsetˇrit ud´ alosti pˇri jeho zav´ır´ an´ı. Pokud bychom tak neuˇcinili, bylo by ho moˇzno zavˇr´ıt pouze zavˇren´ım prvn´ıho okna.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.13: Uk´ azka formul´ aˇre s ikonou.
10.1.3
Pˇ rid´ av´ an´ı dalˇ s´ıch komponent na formul´ aˇ r
Kaˇzd´ a top level-komponenta m´ a zvl´ aˇstn´ı kontejner zvan´ y content pane obsahuj´ıc´ı vˇsechny grafick´e komponenty ”leˇz´ıc´ı” na top level komponentˇe. Tvoˇr´ı ho pouze ˇc´ ast ˇc´ ast komponenty, pod´ıvejme se na n´ asleduj´ıc´ı obr´ azek. Zn´azorˇ nuje formul´ aˇr s komponentou Menu. Content pane pˇredstavuje vnitˇrn´ı ˇc´ ast formul´ aˇre bez titulkov´eho pruhu a menu.
Obr´ azek 10.14: ContentPane a jeho vztah k ostatn´ım ˇc´ astem formul´ aˇre. Obsah content pane je dostupn´ y prostˇrednictv´ım metody getContentPane(). Do kontejneru content pane m˚ uˇzeme dalˇs´ı komponenty pˇrid´ avat metodou add(). Grafick´e komponenty jsou na top level komponenty pˇrid´ av´ any hierarchicky, vytv´ aˇrej´ı stromovou strukturu. Koˇren stromu vytv´ aˇr´ı top-level komponenta. Souˇ radnicov´ y syst´ em komponent. Grafick´e komponenty pouˇz´ıvaj´ı vlastn´ı souˇradnicov´ y syst´em. Jeho poˇc´ atek je v lev´em horn´ım rohu okna. Osa y smˇeˇruje dol˚ u, je pˇredstavov´ ana svislou hranu monitoru, osa x vpravo, je pˇredstavov´ ana vodorovnou hranou monitoru. Hodnoty souˇradnic jsou zad´ av´ any v pixelech. Velikost souˇradnice x je d´ ana hodnotou ˇs´ıˇrky komponenty, m˚ uˇzeme ji zjistit metodou getWidth(). Velikost souˇradnice je d´ ana v´ yˇskou komponenty, m˚ uˇzeme ji zjistit metodou getHeight().
Obr´ azek 10.15: Souˇradnicov´y syt´em komponenty.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Layout managery. Pro pˇrid´ av´ an´ı nov´ ych komponent jsou pouˇz´ıv´ any spr´ avce uspoˇr´ ad´ an´ı, tzv. layout managery. Na r˚ uzn´ ych platform´ ach jsou velikosti grafick´ ych komponent r˚ uzn´e. Layout managery zajist´ı, ˇze pˇri pˇrechodu mezi platformami budou velikosti a poloha jednotliv´ ych komponent automaticky pˇrepoˇcteny (tj. komponenty nebudou nevhodnˇe pˇrekryty ˇci v˚ uˇci sobˇe posunuty) a aplikace bude vypadat neust´ ale hezky :-). V Javˇe se s layout managery pracuje prostˇrednictv´ım tˇr´ıd. Pro nastaven´ı uspoˇr´ ad´ an´ı komponent pouˇz´ıv´ame pˇr´ıkaz setLayout(LayoutManager manager). Parametrem je odkaz ukazuj´ıc´ı na objekt typu LayoutManager. Pro pr´ aci s layout managerem je nutno importovat bal´ık java.awt.*. S layout managery se sezn´ am´ıme podrobnˇeji v dalˇs´ıch kapitol´ ach. Vytvoˇ ren´ı formul´ aˇ re s tlaˇ c´ıtkem. Pokusme se na formul´ aˇr vytvoˇren´ y v pˇredchoz´ı kapitole pˇridat novou komponentu, a to tlaˇc´ıtko JButton a to nejprve bez vyuˇzit´ı layout manageru. O vytvoˇren´ı tlaˇc´ıtka se postar´a n´ asleduj´ıc´ı k´ od JButton but=new JButton("AHOJ"); V konstruktoru prov´ ad´ıme inicializace prostˇrednictv´ım ˇretˇezce pˇredstavuj´ıc´ıho popis tlaˇc´ıtka. Metodou getContentPane() lze z´ıskat kontejner pˇredstavuj´ıc´ı plochu okna, do kter´eho pˇrid´ ame metodou add( Component c) novou komponentu. o.getContentPane.add(but); Cel´ y k´ od bude vypadat takto import javax.swing.*; public class Komponenty { public Komponenty() { Okno o=new Okno(); o.setSize(320, 240); o.setTitle("Moje okno"); JButton but=new JButton("AHOJ"); o.getContentPane.add(but); o.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); o.setVisible(true); } } V´ ysledek n´ as ponˇekud pˇrekvap´ı, tlaˇc´ıtko bude zab´ırat celou plochu okna.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.16: Okno s tlaˇc´ıtkem zab´ıraj´ıc´ım celou jeho plochu. Postup zopakujeme s vyuˇzit´ım layout manageru. Vytvoˇr´ıme novou promˇenou typu FlowLayout obsahuj´ıc´ı odkaz na instanci spr´ avce rozloˇzen´ı komponent FlowLayout f=new FlowLayout(); Metodou setLayout(LayoutManager lm) nastav´ıme pro zvolenou komponentu tento spr´ avce rozloˇzen´ı o.setLayout(f); Oba kroky lze spojit do jednoho. o.setLayout(new FlowLayout()); V´ ysledn´ y k´ od vypad´ a takto import javax.swing.*; import java.awt.*; public class Komponenty { public Komponenty() { Okno o=new Okno(); o.setSize(320, 240); o.setTitle("Moje okno"); o.setLayout(new FlowLayout()); JButton but=new JButton("AHOJ"); o.getContentPane().add(but); o.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); o.setVisible(true); } } Pˇreloˇz´ıme -li a spust´ıme vytvoˇren´ y program, velikost tlaˇc´ıtka jiˇz bude norm´ aln´ı.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.17: Okno s tlaˇc´ıtkem “norm´ aln´ıch” rozmˇer˚ u.
Pˇ r´ıklad: Pokusme se na formul´ aˇri vytvoˇrit v´ıce tlaˇc´ıtek, kter´ a pojmenujeme. Ot´ azkou je, jak budou tlaˇc´ıtka na komponentˇe JFrame uspoˇr´ ad´ ana. V pˇr´ıpadˇe, kdy se nejvejdou do jedn´e ˇr´ adky, pokraˇcuj´ı na ˇr´adce dalˇs´ı. V´ ysledek je patrn´ y na n´ asleduj´ıc´ım obr´ azku. Tlaˇc´ıtka jsou v kaˇzd´e ˇradˇe vycentrov´ ana vzhledem ke komponentˇe, na kter´e leˇz´ı. Podrobnˇeji se s layout managery sezn´ am´ıme v kapitole 1.5.
Obr´ azek 10.18: Okno s vytvoˇren´ ymi tlaˇc´ıtky stejn´ ych rozmˇer˚ u.
10.1.4
Pr´ ace s ud´ alostmi
Na formul´ aˇri jsme vytvoˇrili nˇekolik tlaˇc´ıtek, zat´ım jsme jim vˇsak nepˇriˇradili ˇz´ adnou akci. V t´eto kapitole se sezn´ am´ıme s obsluhou ud´ alost´ı v Javˇe. Jak jsme jiˇz v u ´vodu uvedli, ud´ alost vznik´ a jako d˚ usledek ˇcinnosti uˇzivatele, programu ˇci operaˇcn´ıho syst´emu. Listener. Kaˇzd´ a komponenta m˚ uˇze vyvolat ˇradu r˚ uzn´ ych ud´ alost´ı. V Javˇe existuj´ı speci´ aln´ı instance, kter´e ud´ alosti zachycuj´ı. Naz´ yv´ ame je listenery, tj. posluchaˇci. Urˇcit´ y typ listeneru m˚ uˇze naslouchat pouze jemu odpov´ıdaj´ıc´ımu typu ud´ alosti, listenery tedy funguj´ı adresnˇe. Zdroje ud´ alosti jsou potomky tˇr´ıdy Java.awt.Event. Instance, kter´ a chce pˇrij´ımat ud´ alosti, se mus´ı nejprve jako posluchaˇc zaregistrovat. Zaregistrovan´ y objekt mus´ı implementovat rozhran´ı XXXListener. Lze tak uˇcinit pomoc´ı metody addXXXListener(), kde XXX pˇredstavuje typ ud´ alosti.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Handler. Ud´ alost zp˚ usob´ı zasl´ an´ı zpr´ avy posluchaˇci. D˚ usledkem je vyvol´ an´ı metody oˇsetˇruj´ıc´ı tuto ud´alost, kterou naz´ yv´ ame handler. V handleru n´ aslednˇe provedeme obsluhu ud´ alosti, tj. nˇejak´ ym zp˚ usobem na ni reagujeme. Princip oˇ setˇ ren´ı ud´ alosti V praxi postupujeme tak, ˇze zjist´ıme n´ azev rozhran´ı XXX pro listener zvolen´eho objektu (na z´ akladˇe typu ud´ alosti, kterou budeme oˇsetˇrovat). N´ aslednˇe nalezneme jm´ena metod tohoto rozhran´ı (jejich poˇcet b´ yv´ a r˚ uzn´ y dle typu ud´ alosti) a vˇsechny je implementujeme. Metody nem˚ uˇzeme pˇretˇeˇzovat, pouze pˇredefinovat, sm´ıme je tedy implementovat pouze jednou. Odkaz na instanci tˇr´ıdy, jej´ıˇz jm´eno se shoduje s typem ud´ alosti, pˇred´ av´ ame jako form´ aln´ı parametr handleru oˇsetˇruj´ıc´ımu tuto ud´ alost. Seznam metod a rozhran´ı. V n´ asleduj´ıc´ı tabulce uvedeme pˇrehled nejˇcastˇeji pouˇz´ıvan´ ych ud´ alost´ı, rozhran´ı a jejich metod. Podrobnˇeji se s nimi sezn´ am´ıme v dalˇs´ıch kapitol´ ach. Ud´ alost/Tˇr´ıda
Rozhran´ı
Popis
Metoda
ActionEvent
ActionListener
Proveden´ı akce, napˇr.
actionPerformed()
stisk tlaˇ c´ıtka ComponentEvent
ComponentListener
Zmˇ ena stavu komponenty
ContainerEvent
ContainerListener
FocusEvent
FocusListener
Detekce pˇrid´ an´ı/odebr´ an´ı
componentHidden() componentMoved() componentResized() componentShown() containerAdded() containerRemoved()
komponenty Zmˇ ena zamˇ eˇren´ı
focusGained()
komponenty
focusLost()
ItemEvent
ItemListener
Vybr´ an´ı komponenty
itemStateChanged()
KeyEvent
KeyListener
Pr´ ace s kl´ avesnic´ı
keyPressed() keyReleased()
MouseEvent
MouseListener
Pr´ ace s tlaˇ c´ıtky myˇsi
MouseMotionEvent
MouseMotionListener Pohyb myˇsi
MouseWheelEvent
MouseWheelListener Pr´ ace s rolovac´ım koleˇ ckem myˇsi
mouseWheelMoved()
WindowEvent
WindowListener
windowActivated() windowClosed() windowClosing() windowDeactivated()
WindowFocusEvent
WindowFocusListener Zmˇ ena zamˇ eˇren´ı okna
keyTyped() mouseClicked() mouseEntered() mouseExited() mousePressed() mouseReleased() mouseMotionDragged() mouseMotionMoved()
Zmˇ ena stavu okna
windowOpened() windowFocusGained() WindowFocusLost()
Tabulka 10.1: Pˇrehled ud´ alost´ı, tˇr´ıd, rozhran´ı a metod. Tento na prvn´ı pohled ponˇekud “krkolomn´ y” avˇsak pomˇernˇe logick´ y pˇr´ıstup naznaˇc´ıme na praktick´em pˇr´ıkladˇe. Budeme prov´ adˇet obsluhu ˇcinnosti tlaˇc´ıtka, kter´e jsme vytvoˇrili v pˇredch´ azej´ıc´ı kapitole. Na formul´aˇr
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E pˇrid´ ame novou komponentu zobrazen.
JLabel
pˇredstavuj´ıc´ı pozn´ amku. V konstruktoru je uveden text, kter´ y m´a b´ yt
JLabel lab=new JLabel ("Text"); o.getContentPane().add(lab); Po stisknut´ı tlaˇc´ıtka zobraz´ıme text s vhodnou informac´ı. V tomto pˇr´ıpadˇe pouˇzijeme rozhran´ı ActionListener. Nejprve mus´ıme pro tˇr´ıdu Okno implementovat rozhran´ı ActionListener. Pro pr´ aci s ud´ alostmi je nutno importovat bal´ıˇcek java.awt.event.* s pˇr´ısluˇsn´ ymi ud´ alostmi. import import import public ... }
java.awt.*; java.awt.event.*; javax.swing.*; class Okno extends JFrame implements ActionListener{
Pot´e prostˇrednictv´ım metody addActionListener() zaregistrujeme pro pˇr´ısluˇsnou instanci (tj. komponentu) posluchaˇce. Tento krok je vhodn´ y prov´est v konstruktoru tˇr´ıdy Komponenty. but.addActionListener(this); Nyn´ı vytvoˇr´ıme metodu actionPerformed() oˇsetˇruj´ıc´ı ud´ alost Action komponenty but tˇr´ıdy JButton. public void actionPerformed(ActionEvent e) { lab.setText("Stisknuto tlacitko"); } V´ ysledn´ y k´ od bude vypadat takto: public class Okno extends JFrame implements ActionListener{ private JButton but; private JLabel lab; public Okno(int sirka, int vyska) { this.setSize(sirka,vyska); this.setTitle("Okno"); this.setLayout(new FlowLayout()); but=new JButton("Tlacitko"); lab=new JLabel("Text"); this.getContentPane().add(but); this.getContentPane().add(lab); but.addActionListener(this); this.setVisible(true); } public void actionPerformed(ActionEvent e) { lab.setText("Stisknuto tlacitko"); } }
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Po stisknut´ı tlaˇc´ıtka bude v´ ysledek vypadat takto.
Obr´ azek 10.19: Vlevo v´ychoz´ı formul´ aˇr, vpravo formul´ aˇr po stisknut´ı tlaˇc´ıtka.
D˚ uleˇ zit´ e upozornˇ en´ı. Pokud program obsahuje anonymn´ı vnitˇrn´ı tˇr´ıdu, vznikaj´ı pˇri jeho pˇrekladu soubory obsahuj´ıc´ı pˇred pˇr´ıponou class znak $, kter´e obsahuj´ı pˇreloˇzen´e k´ ody anonymn´ıch vnitˇrn´ıch tˇr´ıd. Nezapomeˇ nme proto pˇri distribuci naˇseho programu tyto tˇr´ıdy pˇriloˇzit. 10.1.4.1
Oˇ setˇ ren´ı stejn´ e ud´ alosti u v´ıce komponent
V programu se ˇcasto vyskytuje v´ıce komponent, kter´e generuj´ı stejn´e typy ud´ alost´ı. Na kaˇzdou z ud´alost´ı zpravidla budeme cht´ıt reagovat jinak. Typick´ ym pˇr´ıkladem jsou r˚ uzn´ a tlaˇc´ıtka, comboboxy ˇci radiobuttony. Komponenty generuj´ı stejn´ y typ ud´ alosti, handler, kter´ y je oˇsetˇruje, nem˚ uˇze b´ yt pˇret´ıˇzen, m˚ uˇze b´ yt implementov´an pouze jednou. Metoda actionPerformed() se ve tˇr´ıdˇe sm´ı vyskytnout pouze jednou. Doporuˇcen´e ˇreˇsen´ı v tomto pˇr´ıpadˇe pˇredstavuje pouˇzit´ı vnitˇrn´ıch tˇr´ıd. popˇr. anonymn´ıch vnitˇrn´ıch tˇr´ıd. My se sezn´am´ıme s druh´ ym pˇr´ıstupem, kter´ y je vyuˇz´ıv´ an ve vˇetˇsinˇe n´ astroj˚ u pro RAD (JBuilder, NetBeans,...). Pˇ r´ıklad s jedn´ım tlaˇ c´ıtkem. Rozhran´ı, kter´e je moˇzno implementovat, jsou uvedena v tabulce v u ´ vodu kapitoly 1.4. Budeme se snaˇzit oˇsetˇrit ud´ alost ActionEvent rozhran´ı ActionListener. Rozhran´ı jiˇz nebude implementov´ ano tˇr´ıdou Okno, ale nˇejakou anonymn´ı vnitˇrn´ı tˇr´ıdou. Toto rozhran´ı obsahuje metodu actionPerformed(), kter´ a bude uˇzivatelem pˇredefinov´ ana. Nejprve provedeme registraci posluchaˇce. but.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { tlStisknuto(e); } }); Metodˇe addActionListener() pˇred´ av´ ame jako parametr instanci anonymn´ı tˇr´ıdy implementuj´ıc´ı rozhran´ı ActionListener. Metoda tlStisknuto()pˇredstavuje handler, kter´ y je vyvol´ an, pokud dojde k pˇr´ısluˇsn´e ud´ alosti. V naˇsem pˇr´ıpadˇe obsahuje pouze k´ od, kter´ y do komponenty JLabel um´ıst´ı informaci o tom, ˇze tlaˇc´ıtko bylo stisknuto. public void tlStisknuto(ActionEvent e) { lab.setText("Stisknuto tlacitko"); } Pˇ r´ıklad se dvˇ ema tlaˇ c´ıtky. Stejn´ ym zp˚ usobem budeme postupovat i v pˇr´ıpadˇe, kdy se budeme snaˇzit rozliˇsit, kter´e z tlaˇc´ıtek bylo stisknuto. Vytvoˇr´ıme dvˇe tlaˇc´ıtka, zaregistrujeme jim posluchaˇce a u obou pˇredefinujeme metody actionPerformed(). Uvedeme cel´ y zdrojov´ y k´ od.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E public class Okno2 extends JFrame { private JButton but1, but2; private JLabel lab; public Okno2(int sirka, int vyska) { this.setSize(sirka,vyska); this.setTitle("Okno"); this.setLayout(new FlowLayout()); but1=new JButton("Tlacitko1"); but2=new JButton("Tlacitko2"); lab=new JLabel("Text"); this.getContentPane().add(but1); this.getContentPane().add(but2); this.getContentPane().add(lab); but1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { tl1Stisknuto(e); } }); but2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { tl2Stisknuto(e) ; } }); this.setVisible(true); } public void tl1Stisknuto(ActionEvent e) { lab.setText("Stisknuto prvni tlacitko"); } public void tl2Stisknuto(ActionEvent e) { lab.setText("Stisknuto druhe tlacitko"); } } Podobn´ y k´ od je generov´ an prostˇrednictv´ım RAD n´ astroj˚ u. V´ ysledek vypad´ a takto:
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.20: Vlevo v´ychoz´ı formul´ aˇr, uprostˇred po stisknut´ı lev´eho tlaˇc´ıtka, vpravo po stisknut´ı prav´eho tlaˇc´ıtka. 10.1.4.2
Nˇ ekolik posluchaˇ c˚ u t´ eˇ ze ud´ alosti
ˇ Casto potˇrebujeme, aby jedna ud´ alost mˇela v´ıce posluchaˇc˚ u. Napˇr. pˇri stisku tlaˇc´ıtka potˇrebujeme, aby se provedlo nˇekolik r˚ uzn´ ych ˇcinnost´ı. V tomto pˇr´ıpadˇe nemus´ıme rozliˇsovat zdroj akce, nen´ı tˇreba pouˇz´ıvat anonymn´ı vnitˇrn´ı tˇr´ıdy jako v pˇredchoz´ım pˇr´ıpadˇe. public Okno2(int sirka, int vyska) { this.setSize(sirka,vyska); this.setTitle("Okno"); this.setLayout(new FlowLayout()); but1=new JButton("Tlacitko1"); but2=new JButton("Tlacitko2"); lab=new JLabel("Text"); this.getContentPane().add(but1); this.getContentPane().add(but2); this.getContentPane().add(lab); but1.addActionListener(but1); but1.addActionListener(but2); ... }
10.1.5
Barvy, fonty, grafick´ y vzhled komponent
V t´eto kapitole se sezn´ am´ıme se z´ akladn´ımi informacemi o barv´ ach a fontech v jazyce Java. 10.1.5.1
Barvy v Javˇ e
Java pracuje s modelem RGB, kter´ y pouˇz´ıv´ a tˇri z´ akladn´ı barevn´e sloˇzky: ˇcervenou (Red), zelenou (Green), modrou (Blue). Kaˇzd´ a ze sloˇzek m˚ uˇze nab´ yvat intenzitu v intervalu <0,255>. Existuje tedy 2563 r˚ uzn´ ych barevn´ ych odst´ın˚ u. Pro pr´ aci s barvami je pouˇzita tˇr´ıda java.awt.Color. V Javˇe je pˇreddefinov´ ano 13 nejˇcastˇeji pouˇz´ıvan´ ych barevn´ ych odst´ın˚ u, pˇredstavuj´ı objekty tˇr´ıdy Color. Jejich pˇrehled je uveden v n´ asleduj´ıc´ı tabulce.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Barva
Popis
Color.black
ˇ cern´ a
Color.white
b´ıl´ a
Color.red
ˇ cerven´ a
Color.green
zelen´ a
Color.blue
modr´ a
Color.yellow
ˇ zlut´ a
Color.cyan
azurov´ a
Color.magenta
fialov´ a
Color.orange
oranˇ zov´ a
Color.pink
r˚ uˇ zov´ a
Color.lightGray
svˇ etle ˇsed´ a
Color.gray
ˇsed´ a
Color.darkGrey
tmavˇ e ˇsed´ a.
Chceme -li zkonstruovat barvu vlastn´ı, je nutno vytvoˇrit instanci tˇr´ıdy Color. V konstruktoru uvedeme hodnoty jednotliv´ ych RGB sloˇzek. Color zelena=new Color (140,140,140); Kaˇzd´ a z komponent m´ a popˇred´ı (foreground) a pozad´ı (background). Pro popˇred´ı i pozad´ı lze nastavit barvu nebo tyto u ´daje z´ıskat. Barva popˇred´ı pˇredstavuje barvu textu, s n´ıˇz je komponenta pops´ ana, barva pozad´ı pak barvu vlastn´ı komponenty. Pro pr´ aci s barvou popˇred´ı jsou pouˇzity metody setForeground(Color col) a getForeground(), pro pr´ aci s pozad´ım metody setBackground(Color col) a getBackground(). V prvn´ım pˇr´ıkladu se pokus´ıme zmˇenit barvu pozad´ı tlaˇc´ıtka a jeho popisu na nˇekter´ y z pˇreddefinovan´ ych odst´ın˚ u. public class Okno3 extends JFrame{ public Okno3(int sirka, int vyska) { this.setSize(sirka, vyska); this.setTitle("Okno"); JButton b=new JButton("Pokus"); this.getContentPane().add(b); this.setLayout(new FlowLayout()); b.setBackground(Color.blue); b.setForeground(Color.red); this.setVisible(true); } } V´ ysledek vypad´ a takto
Obr´ azek 10.21: Barva popˇred´ı tlaˇc´ıtka: ˇcerven´ a, barva pozad´ı tlaˇc´ıtka: modr´ a. V dalˇs´ım pˇr´ıkladu se pokus´ıme zmˇenit barvu tlaˇc´ıtka na vlastn´ı hodnotu. Nepouˇzijeme pˇreddefinovan´ y odst´ın, vytvoˇr´ıme vlastn´ı objekt tˇr´ıdy Color.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E b.setBackground(new (140,140,140)); b.setForeground(new Color(150,250,180)); ˇ Hodnoty barevn´ ych sloˇ zek Casto potˇrebujeme zjistit hodnoty jednotliv´ ych barevn´ ych sloˇzek. K tomu slouˇz´ı tˇri metody: getRed(), getGreen(), getBlue(). V´ ysledkem jsou hodnoty typu int. 10.1.5.2
Fonty v Javˇ e
Java m˚ uˇze bˇeˇzet na r˚ uzn´ ych operaˇcn´ıch syst´emech, na kaˇzd´em z nich se mohou vyskytovat jin´e typy font˚ u. Java proto pouˇz´ıv´ a syst´em tzv. symbolick´ ych font˚ u, kter´e jsou nez´ avisl´e na platformˇe. Existuje pˇet z´ akladn´ıch skupin font˚ u (tzv. rodin), od kter´ ych lze odvodit 4 ˇrezy (plain, bold, italic, bolditalic). Jejich pˇrehled a srovn´ an´ı s fonty OS Windows je uveden v n´ asleduj´ıc´ı tabulce. OS Windows
Java
TimesNewRoman
Serif
Arial
SansSerif
CourierNew
Monospaced
Arial
Dialog
CourierNew
DialogInput
Tabulka 10.2: Pˇrehled z´ akladn´ıch font˚ u a jejich ˇrez˚ u. ´ Pro pr´ aci s fonty Java pouˇz´ıv´ a tˇr´ıdu java.awt.Font. Udaje o fontu se nach´ azej´ı v instanci tˇr´ıdy Font. Jej´ı konstruktor vypad´ a takto. Font f =new Font("Serif", Font.bold,10); Z´ısk´ an´ı informac´ı o fontu. Pro z´ısk´ an´ı informac´ı o fontu pouˇzijeme metodu getFont() vracej´ıc´ı hodnotu tˇr´ıdy font. Na n´ı lze aplikovat ˇradu dalˇs´ıch metod: getFamily(), isPlain(), isBold(), isItalic(). 10.1.5.3
Z´ akladn´ı vlastnosti komponent
V t´eto kapitole se sezn´ am´ıme se z´ akladn´ımi vlastnostmi, kter´e jsou spoleˇcn´e vˇetˇsinˇe komponent. Zjiˇ stˇ en´ı velikosti a polohy komponenty. Pro zjiˇstˇen´ı velikosti komponenty slouˇz´ı metody getWidth() a getHeight(). V´ ysledkem jsou hodnoty typu int. Existuje i metoda getSize() vracej´ıc´ı obˇe hodnoty souˇcasnˇe. Polohu komponenty vzhledem k lev´emu horn´ımu rohu okna m˚ uˇzeme urˇcit prostˇrednictv´ım metod getX() a getY(). Do t´eto hodnoty se nepoˇc´ıt´ a v´ yˇska titulkov´eho pruhu formul´ aˇre. Velikost komponenty m˚ uˇzeme zmˇenit prostˇrednictv´ım metody setSize(int width, int height), polohu komponenty prostˇrednictv´ım setLocation(). Existuj´ı i jejich varianty s get, getSize() a getLocation(). Nastaven´ı extr´ emn´ı velikosti komponenty Kaˇzd´e z komponent je moˇzno nastavit minim´ aln´ı, maxim´ aln´ı, ˇci preferovanou velikost. Slouˇz´ı k tomu metody setMinimumSize(int width, int height), setMaximumSize( int width, int height), setPrefferedSize(int width, int height). Preferovan´ a velikost komponenty je v´ ychoz´ı velikost komponenty, defaultnˇe je nastavena jako minim´ aln´ı velikost komponenty. Pro zjiˇstˇen´ı v´ yˇse nastaven´ ych u ´daj˚ u slouˇz´ı metody getMinimumSize(), getMaximumSize(), getPrefferedSize().
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Zpˇ r´ıstupnˇ en´ı/znepˇ r´ıstupnˇ en´ı komponenty. Komponenta se m˚ uˇze vyskytovat ve dvou z´ akladn´ıch stavech: komponenta je aktivn´ı, jsou nad n´ı generov´ any ud´ alosti, oznaˇcujeme ji jako pˇr´ıstupnou. V opaˇcn´em pˇr´ıpadˇe je komponenta nepˇr´ıstupn´ a a tud´ıˇz neaktivn´ı, je zn´ azornˇena ˇsedou barvou. Tato vlastnost komponenty je pouˇz´ıv´ ana, pokud chceme uˇzivateli zak´ azat/povolit nˇejakou akci. Nen´ı vhodn´e komponenty odeb´ırat, nepˇrisp´ıv´ a to k pˇrehlednosti programu. Uˇzivatel bude zmaten, kam zmizely jeho obl´ıben´e n´ astroje. Pro zpˇr´ıstupnˇen´ı/znepˇr´ıstupnˇen´ı komponenty je pouˇz´ıv´ ana metoda setEnabled(boolean status). Metoda m´a jako parametr hodnotu typu boolean. Zjiˇstˇen´ı stavu, zda je komponenta pˇr´ıstupn´ a ˇci ne, pouˇzijeme pˇr´ıkaz getEnabled(). Pod´ıvejme se na jednoduch´ y program, kter´ y ilustruje pˇr´ıstupnost komponenty na pˇr´ıkladu dvou tlaˇc´ıtek. Po stisknut´ı jednoho z nich se druh´e tlaˇc´ıtko stane nepˇr´ıstupn´ ym. Opakovan´ ym stisknut´ım tlaˇc´ıtka se druh´e tlaˇc´ıtko opˇet st´ av´ a aktivn´ım. V´ ysledn´ y k´ od m˚ uˇze vypadat napˇr. takto. public class Okno4 extends JFrame{ private JButton b1, b2; public Okno4(int sirka, int vyska) { this.setSize(sirka, vyska); this.setTitle("Okno"); this.setLayout(new FlowLayout()); b1=new JButton(); b2=new JButton(); b1.setText("Zapnuto"); b2.setText("Zapnuto"); this.getContentPane().add(b1); this.getContentPane().add(b2); this.setVisible(true); b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { tl1Stisknuto(e); } }); b2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e ) { tl2Stisknuto(e); } }); } public void tl1Stisknuto(ActionEvent e) { b2.setEnabled(!b2.isEnabled()); if (b2.isEnabled()) b2.setText("Zapnuto"); else b2.setText("Vypnuto"); } public void tl2Stisknuto(ActionEvent e) { b1.setEnabled(!b1.isEnabled()); if (b1.isEnabled()) b1.setText("Zapnuto"); else b1.setText("Vypnuto"); } } A v´ ysledek:
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.22: Uk´ azky zpˇr´ıstupnˇen´ı a znepˇr´ıstupˇ nov´ an´ı komponent. yt. Slouˇz´ı k tomu metoda setViSkryt´ı/zobrazen´ı komponenty. Komponentu je moˇzno zobrazit ˇci skr´ sible(boolean status) s parametrem typu boolean. Stav komponenty lze zjistit metodou isVisible().
Obr´ azek 10.23: Skryt´ı komponenty.
10.1.6
Layout managery
Pˇri rozmist’ov´ an´ı komponent na formul´ aˇre (ˇci jin´e komponenty) zpravidla v Javˇe nedefinujeme polohu komponent absolutnˇe. D˚ uvodem je fakt, ˇze Java m˚ uˇze bˇeˇzet na r˚ uzn´ ych prostˇred´ıch, kde jednotliv´e grafick´e komponenty nemusej´ı m´ıt stejnou velikost ˇci tvar. Takov´ y program by na nˇekter´ ych platform´ ach nevypadal vˇzdy pˇeknˇe, mohlo doj´ıt napˇr. k pˇrekryt˚ um nˇekter´ ych jeho grafick´ ych komponent, jin´e by se na formul´aˇr nemusely vej´ıt cel´e. M´ısto toho pouˇz´ıv´ ame tzv. layout managery (spr´ avce uspoˇr´ ad´ an´ı), kter´e jsou zodpovˇedn´e za rozm´ıstˇen´ı komponent. Pˇri pˇrechodu mezi r˚ uzn´ ymi prostˇred´ımi prov´ adˇej´ı pˇrepoˇcet polohy a tvaru komponent. Existuje pˇet typ˚ u spr´avc˚ u uspoˇr´ ad´ an´ı, kaˇzd´ a z komponent m´ a sv˚ uj vlastn´ı implicitn´ı spr´ avce uspoˇr´ ad´ an´ı; ten vˇsak m˚ uˇzeme zmˇenit za pouˇzit´ı metody setLayout(LayoutManager lm). Typy layout manager˚ u. LayoutManager pˇredstavuje objekt tˇr´ıdy java.awt.LayoutManager, tvoˇr´ı ji nˇekolik dalˇs´ıch tˇr´ıd. Komplexnˇejˇs´ı popis t´eto problematiky pˇresahuje rozsah tohoto materi´ alu, pod´ıv´ame se na tˇri nejˇcastˇeji pouˇz´ıvan´e layout managery: • FlowLayout • GridLayout • BorderLayout Prvn´ı dva layout managery jsou pomˇernˇe jednoduch´e, tˇret´ı umoˇzn ˇuje prov´ adˇet pokroˇcilejˇs´ı rozvrˇzen´ı komponent.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Okno a kontejner. Pˇripomeˇ nme, ˇze kaˇzd´e okno obsahuje kontejner, jehoˇz obsah m˚ uˇzeme z´ıskat metodou getContentPane(). Do kontejneru m˚ uˇzeme pˇrid´ avat komponenty metodou add(Component c). N´ avrh vzhledu aplikace. S pouˇzit´ım layout manager˚ u m˚ uˇzeme navrhovat i znaˇcnˇe vzhledovˇe sloˇzit´a grafick´a rozhran´ı tvoˇren´ a velk´ ym mnoˇzstv´ım komponent. Tento postup je vˇsak pomˇernˇe n´ aroˇcn´ y, vytvoˇren´ı takov´eho rozhran´ı zabere spoustu ˇcasu. Je proto vhodn´e ho prov´ adˇet nˇekter´ ym z n´ astroj˚ u pro RAD obsahuj´ıc´ıho tzv. GUI buildery. Do t´eto skupiny patˇr´ı napˇr. JBuilder nebo NetBeans. V praxi se prov´ ad´ı pˇri “ruˇcn´ım” n´ avrhu rozdˇelen´ı okna na nˇekolik r˚ uzn´ ych ˇc´ ast´ı, kter´e obsahuj´ı mal´e mnoˇzstv´ı ˇ komponent. Vzhled kaˇzd´e takto vznikl´e ˇc´ asti je navrhov´ an samostatnˇe. Casto nevystaˇc´ıme s jedn´ım layout managerem, m˚ uˇzeme je proto vz´ ajemnˇe kombinovat. My budeme ˇcinnost layout manager˚ u ilustrovat pouze na jednoduch´ ych pˇr´ıkladech. 10.1.6.1
FlowLayout
FlowLayout pˇredstavuje nejjednoduˇsˇs´ı layout manager. V pˇredch´ azej´ıc´ıch kapitol´ ach jsme se s n´ım jiˇz sezn´ amili. Pˇripomeˇ nme si, ˇze jednotliv´e komponenty uspoˇr´ ad´ av´ a do ˇr´ adky za souˇcasn´eho vycentrov´ an´ı; mezi komponentami jsou ponech´ any mezery. Pokud se jiˇz komponenty na ˇr´ adek nevejdou, pokraˇcuje se na dalˇs´ım ˇr´ adku. V´ yˇska ˇr´ adku je d´ ana nejvyˇsˇs´ı komponentou. Komponenty mohou b´ yt zarovn´ any tak´e nalevo nebo napravo. K dispozici je nˇekolik konstruktor˚ u FlowLayout(); FlowLayout(typ_zarovnani); FlowLayout(typ_zarovnani, vod_mezera, svisla_mezera); Typ zarovn´an´ı lze zvolit prostˇrednictv´ım konstant: FlowLayout.CENTER, FlowLayout.RIGHT, FlowLayout.LEFT. Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad. public class Okno extends JFrame{ public Okno() { this.setSize(320,240); this.setTitle("Okno"); this.setLayout(new FlowLayout(FlowLayout.RIGHT,5,5)); JButton but1=new JButton("Ahoj"); this.getContentPane().add(but1); JButton but2=new JButton("Druhe"); this.getContentPane().add(but2); JButton but3=new JButton("Treti"); this.getContentPane().add(but3); JButton but4=new JButton("Ctvrte"); this.getContentPane().add(but4); JButton but5=new JButton("Pate"); this.getContentPane().add(but5); JButton but6=new JButton("Seste"); this.getContentPane().add(but6); this.setVisible(true); } Zmˇenou typu zarovn´ an´ı dostaneme n´ asleduj´ıc´ı v´ ysledek.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.24: Zmˇena zarovn´ an´ı komponent pˇri Flow Layoutu. 10.1.6.2
GridLayout
GridLayout pˇredstavuje layout manager, kter´ y jednotliv´e komponenty zarovn´ av´ a do mˇr´ıˇzky tvoˇren´e stejnˇe velk´ ymi poli. Komponenta se pomyslnˇe rozdˇel´ı na stejnˇe velk´e ˇc´ ast´ı tvoˇren´e rovnobˇeˇzkami z hranami formul´ aˇre, do kaˇzd´eho d´ılu je um´ıstˇena jedna komponenta. Pokud jsou vˇsechna pol´ıˇcka v ˇr´ adku zaplnˇena, pˇrech´az´ı se na dalˇs´ı ˇr´ adek. Velikost jednoho pol´ıˇcka je nastavena na z´ akladˇe nejvˇetˇs´ı komponenty. Uved’me opˇet nˇekter´e d˚ uleˇzit´e konstruktory. GridLayout(); GridLayout(radky, sloupce); GridLayout(radky, sloupce, vod_mezera, svisla_mezera); Prvn´ı konstruktor umoˇzn´ı vloˇzit pouze jednu komponentu roztaˇzenou pˇres cel´e okno. Pokud pouˇzijeme druh´ y konstruktor, budou se jednotliv´e komponenty dot´ ykat, tj. mezery mezi nimi budou stejn´e. Pouˇzijeme stejn´ y k´ od jako v pˇredchoz´ım pˇr´ıpadˇe, pouze zmˇen´ıme layout manager. V prvn´ım pˇr´ıpadˇe pouˇzijeme konstruktory GridLayout(3,2), ve druh´em pˇr´ıpadˇe GridLayout(3,2,10,10). V´ ysledky budou vypadat takto.
Obr´ azek 10.25: Pouˇzit´ı dvou konstruktor˚ u tˇr´ıdy GridLayout. 10.1.6.3
BorderLayout
Border Layout pˇredstavuje layout manager, kter´ y jednotliv´e komponenty umist’uje podle svˇetov´ ych stran na z´ akladˇe hodnot konstant BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST, BorderLay-
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E out.WEST, BorderLayout.CENTER. Komponenty nejsou, na rozd´ıl od pˇredch´ azej´ıc´ıch spr´ avc˚ u, ˇrazeny podle podle poˇrad´ı. Velikosti jednotliv´ ych komponent jsou r˚ uzn´e: severn´ı a jiˇzn´ı komponenta jsou roztaˇzeny na maxim´ aln´ı ˇs´ıˇrku, severn´ı a jiˇzn´ı komponenty na maxim´ aln´ı v´ yˇsku, velikost stˇredov´e komponenty se nemˇen´ı. Pouˇzit´ı nalezne napˇr. pˇri navrhov´ an´ı ovl´ adac´ıch tlaˇc´ıtek pro pohyb kurzoru. K dispozici jsou dva konstruktory: BorderLayout(); BorderLayout(vod_mezera, svisla_mezera); Pˇri pouˇzit´ı prvn´ıho konstruktoru nejsou mezi jednotliv´ ymi komponentami mezery, u druh´eho konstruktoru lze nastavit vodorovn´e a svisl´e rozestupy mezi komponentami. Zdrojov´ y k´ od lze zapsat napˇr. takto public Okno() { this.setSize(320,240); this.setTitle("Okno"); this.setLayout(new GridLayout()); this.setLayout(new BorderLayout(10,10)); JButton but1=new JButton("Ahoj"); this.getContentPane().add(but1, BorderLayout.NORTH); JButton but2=new JButton("Druhe"); this.getContentPane().add(but2, BorderLayout.SOUTH); JButton but3=new JButton("Treti"); this.getContentPane().add(but3, BorderLayout.EAST); JButton but4=new JButton("Ctvrte"); this.getContentPane().add(but4, BorderLayout.WEST); JButton but5=new JButton("Pate"); this.getContentPane().add(but5, BorderLayout.CENTER); this.setVisible(true); } V´ ysledek vypad´ a takto.
Obr´ azek 10.26: Pouˇzit´ı dvou konstruktor˚ u tˇr´ıdy BorderLayout. Pozn´ amka: CardLayout manager nebudeme z d˚ uvodu omezen´e pouˇzitelnosti uv´ adˇet, GridBackLayout manager je pomˇernˇe sloˇzit´ y. Z´ ajemce se s nimi m˚ uˇze sezn´ amit v dostupn´e literatuˇre. Pro v´ yvoj sloˇzitˇejˇs´ıch GUI aplikac´ı budeme pouˇz´ıvat n´ astroje RAD, nemus´ıme tak ztr´ acet ˇcas a energii pˇri n´ avrhu grafick´eho vzhledu, uˇsetˇren´ y ˇcas a prostˇredky mohou b´ yt vˇenov´ any na zdokonalov´ an´ı aplikace.
10.1.7
Modely v Javˇ e
V GUI Javy je ˇcasto vyuˇz´ıvan´ ym postupem pr´ ace s modelem. Model pˇredstavuje implementaci nˇejak´eho rozhran´ı jinou (napˇr. grafickou) tˇr´ıdou. Pˇres toto rozhran´ı pˇristupuje grafick´ a tˇr´ıda ke sv´ ym metod´ am. Pouˇzit´ı model˚ u umoˇzn ˇuje d˚ uslednˇe oddˇelit grafick´ y n´ avrh aplikace od funkˇcn´ı ˇc´ asti.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Modely se pouˇz´ıvaj´ı nejen pro pr´ aci s grafikou, setk´ ame se s nimi i pˇri manipulac´ıch s bˇeˇzn´ ymi komponentami. Koncept rozhran´ı v Javˇe je tvoˇren tˇremi skupinami rozhran´ı: • Z´akladn´ı rozhran´ı. • Abstraktn´ı implementace rozhran´ı. • V´ ychoz´ı implementace rozhran´ı. Z´ akladn´ı rozhran´ı pro pr´ aci s modely pˇredstavuj´ı napˇr. TableModel, ListModel, ... Abstraktn´ı implementace (implementace rozhran´ı abstraktn´ı tˇr´ıdou) pouˇz´ıv´ ame v pˇr´ıpadech, kdy chceme pˇredefinov´ avat funkcionalitu rozhran´ı (napˇr. AbstractTableModel), v´ ychoz´ı implementaci rozhran´ı (implementace rozhran´ı neabstraktn´ı tˇr´ıdou) v pˇr´ıpadech, kdy funkcionalitu rozhran´ı nemˇen´ıme napˇr. DefaultTableModel). Problematika model˚ u v Javˇe jde nad r´ amec z´ akladn´ıho kurzu, proto se o n´ı zmiˇ nujeme pouze velmi struˇcnˇe. Modely umoˇzn ˇuj´ı tak´e pracovat s ud´ alostmi. Pokud dojde k jak´ekoliv zmˇenˇe v datech modelu, je tato informace ozn´amena vˇsem zaregistrovan´ ym posluchaˇc˚ um. Modely se pouˇz´ıvaj´ı ˇcasto pˇri pr´ aci s n´ asleduj´ıc´ımi komponentami: • JList (Seznam) • JTable (Tabulka) • JTree (Strom) Uved’me pro u ´plnost, ˇze s tˇemito komponentami m˚ uˇzeme pracovat i “klasicky”, tj. bez pouˇzit´ı model˚ u.
10.1.8
Pˇ rehled nejpouˇ z´ıvanˇ ejˇ s´ıch komponent
V t´eto kapitole se sezn´ am´ıme s nejˇcastˇeji pouˇz´ıvan´ ymi vizu´ aln´ımi komponentami a jejich ud´ alostmi. Jsou potomky tˇr´ıdy javax.Swing.*, kromˇe t´eto tˇr´ıdy mus´ıme pˇripojit i tˇr´ıdu java.awt.event.*. N´ azev komponenty zaˇc´ınaj´ıc´ı na p´ısmeno J je souˇcasnˇe i n´ azvem tˇr´ıdy, kterou komponenta pˇredstavuje. Zopakujme, ˇze starˇs´ı komponenty z rozhran´ı AWT maj´ı podobn´e n´ azvy, pouze nezaˇc´ınaj´ı p´ısmenkem J. Spoleˇcnou vlastnost´ı vˇsech komponent popsan´ ych v kapitol´ ach 10.8.1-10.8.8 je to, ˇze nemohou b´ yt zobrazeny samostatnˇe (pˇredstavuj´ı z´ akladn´ı komponenty). Nen´ı moˇzn´e vytvoˇrit program, kter´ y zobraz´ı pouze jednu tuto komponentu (napˇr. JLabel) bez hlavn´ıho okna. 10.1.8.1
JLabel
Tato komponenta je pouˇz´ıv´ ana jako popis. Neobsahuje -li ˇz´ adn´ y text, je neviditeln´ a. Komponentˇe lze nastavit barvu popˇred´ı nebo barvu pozad´ı. Standardnˇe je v n´ı text zarovn´ an smˇerem vlevo. Vˇetˇsinou je pouˇz´ıv´ana jako komponenta “statick´ a”, kdy zpravidla neoˇsetˇrujeme jeho ud´ alosti, ale pouze s n´ım popisujeme jin´e komponenty. Existuj´ı tˇri z´ akladn´ı konstruktory tˇr´ıdy JLabel. JLabel(); JLabel(String text); JLabel (String text, JLabel alignment);
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Zarovn´ an´ı lze ovlivnit tˇremi konstantami: JLabel.LEFT, JLabel.RIGHT, JLabel.CENTER, JLabel.LEADING, JLabel.TRAILING. Pˇrehled nejpouˇz´ıvanˇejˇs´ıch metod spolu se struˇcn´ ym popisem jsou um´ıstˇeny v n´ asleduj´ıc´ı tabulce. Metoda
Popis
setText()
Nastaven´ı textu zobrazovan´ eho labelem
getText()
Z´ısk´ an´ı textu zobrazovan´ eho labelem.
setHorizontalAlignment()
Nastaven´ı horizont´ aln´ıho zarovn´ an´ı textu v labelu.
getHorizontalAlignment()
Z´ısk´ an´ı horizont´ aln´ıho zarovn´ an´ı textu v labelu.
setVerticalAlignment()
Nastaven´ı vertik´ aln´ıho zarovn´ an´ı textu v labelu.
getVerticalAlignment()
Z´ısk´ an´ı vertik´ aln´ıho zarovn´ an´ı textu v labelu.
Tabulka 10.3: Pˇrehled metod tˇr´ıdy JLabel. Praktick´e pˇr´ıklady uv´ adˇet nebudeme, pouˇzit´ı JLabelu je trivi´ aln´ı. Nav´ıc jsme si pr´ aci s touto komponentou v pˇredchoz´ım textu jiˇz vyzkouˇseli. 10.1.8.2
JButton
JButton neboli tlaˇc´ıtko pˇredstavuje jednu z nejpouˇz´ıvanˇejˇs´ıch komponent, zpravidla slouˇz´ı ke spouˇstˇen´ı nˇejak´e akce. K dispozici jsou dva z´ akladn´ı konstruktory: JButton(); JButton(String text); Tlaˇc´ıtko po sv´em stisknut´ı generuje ud´ alost, kterou je nutn´e odchytit prostˇrednictv´ım rozhran´ı ActionListener za pouˇzit´ı metody actionPerformed. Pˇredhled metod pouˇz´ıvan´ ych u tlaˇc´ıtka. Metoda
Popis
setText()
Nastaven´ı popisu tlaˇ c´ıtka.
getText()
Z´ısk´ an´ı popisu tlaˇ c´ıtka.
Tabulka 10.4: Pˇrehled metod tˇr´ıdy JButton.
10.1.8.3
JCheckBox
JCheckBox pˇredstavuje zaˇskrt´ avac´ı pole, m˚ uˇze nab´ yvat logick´e hodnoty true/false (realizovan´e zaˇskrtnu-
t´ım/odˇskrtnut´ım). CheckBoxy je moˇzno seskupovat, komponenty jsou na sobˇe nez´ avisl´e; mohou b´ yt zaˇskrtnuty/odˇskrtnuty v libovoln´e kombinaci. Z´ akladn´ı konstruktory vypadaj´ı takto: JCheckBox(); JCheckBox(String text); JCheckBox(String text, boolean status); Prvn´ı konstruktor vytvoˇr´ı JCheckBox bez popisu a bez zaˇskrtnut´ı, druh´ y s popisem a bez zaˇskrtnut´ı, tˇret´ı s popisem a moˇznost´ı volby zaˇskrtnut´ı. Pˇrehled metod pouˇz´ıvan´ ych u check box˚ u nalezeneme v n´ asleduj´ıc´ı tabulce
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Metoda
Popis
setText( text)
Nastaven´ı popisu checkboxu.
getText()
Z´ısk´ an´ı popisu checkboxu.
setSelected(boolean status)
Nastaven´ı stavu checkboxu.
isSelected()
Z´ısk´ an´ı stavu checkboxu.
Tabulka 10.5: Pˇrehled metod tˇr´ıdy JCheckBox. Pˇri zmˇenˇe stavu checkboxu je generov´ ana ud´ alost, kterou lze odchytit prostˇrednictv´ı rozhran´ı ItemListener za pouˇzit´ı metody itemStateChanged(). Pod´ıvejme se na n´ asleduj´ıc´ı pˇr´ıklad, kter´ y bude zobrazovat stav zaˇskrtnut´ı dvou JCheckBox˚ u ve dvou JLabelech. V´ ysledek vypad´ a takto.
Obr´ azek 10.27: Uk´ azka pr´ ace s checkboxy. Zdrojov´ y k´ od pˇr´ıkladu, vyuˇz´ıv´ ame GridLayout. public class Checkboxy extends JFrame { private JCheckBox c1, c2; private JLabel l1,l2; public Checkboxy(int vyska, int sirka) { this.setSize(vyska, sirka); this.setTitle("Checkboxy"); c1=new JCheckBox("Prvn´ ı"); c2=new JCheckBox("Druhy"); l1=new JLabel(c1.getText()); l2=new JLabel(c2.getText()); this.getContentPane().add(c1); this.getContentPane().add(c2); this.getContentPane().add(l1); this.getContentPane().add(l2); this.setLayout(new GridLayout(2,2)); c1.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { l1Changed(e); } }); c2.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { l2Changed(e); } }); } public void l1Changed(ItemEvent e) {
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E if(c1.isSelected()) l1.setText("Zaˇ skrtnuto"); else l1.setText("Odˇ skrtnuto"); } public void l2Changed(ItemEvent e) { if(c2.isSelected()) l2.setText("Zaˇ skrtnuto"); else l2.setText("Odˇ skrtnuto"); } } 10.1.8.4
JRadioButton
Tato komponenta se sv´ ym tvarem podob´ a JCheckBoxu, tlaˇc´ıtko je vˇsak kulat´e. Od check box˚ u se odliˇsuje zp˚ usobem v´ ybˇeru, v pˇr´ıpadˇe skupiny radio button˚ u m˚ uˇze b´ yt v jednom okamˇziku vybr´ ano pouze jedno tlaˇc´ıtko. Radiobuttony mohou b´ yt pouˇz´ıv´ any samostatnˇe nebo sdruˇzov´ any do skupiny prostˇrednictv´ım komponenty JButtonGroup. Pokud um´ıst´ıme radio buttony na formul´ aˇr, aniˇz je sdruˇz´ıme do skupiny, mohou b´ yt vyb´ır´ any nez´avisle na sobˇe (nevˇed´ı vz´ ajemnˇe o sv´em stavu). To, ˇze je sdruˇz´ıme do skupiny, zp˚ usob´ı, ˇze vybran´ y radiobutton ”informuje” ostatn´ı radio buttony skupiny, takˇze jiˇz nemohou b´ yt n´ aslednˇe vybr´ any. K dispozici je vˇetˇs´ı mnoˇzstv´ı konstruktor˚ u, uved’me tyto: JRadioButton(); JRadioButton(String text); JRadioButton(String text, boolean selected); Prvn´ı konstruktor vytvoˇr´ı pr´azdn´ y nevybran´ y radio button, druh´ y konstruktor nevybran´ y radio button s popisem, tˇret´ı konstruktor radio button s popisem, u kter´eho m˚ uˇzeme zvolit v´ ychoz´ı stav. V praxi postupujeme nejˇcastˇeji tak, ˇze vytvoˇr´ıme poˇzadovan´ y poˇcet radio button˚ u a n´ aslednˇe kaˇzd´ y z nich pˇriˇrad´ıme do skupiny. Pˇrehled nejˇcastˇeji pouˇz´ıvan´ ych metod u JRadioButton˚u. Metoda
Popis
isSelected()
Z´ısk´ an´ı stavu checkboxu.
setSelected()
Nastaven´ı stavu checkboxu.
Tabulka 10.6: Pˇrehled metod tˇr´ıdy JRadioButton. Pˇri pr´ aci s tˇr´ıdou ButtonGroup je k dispozici jedin´ y konstruktor ButtonGroup(); vytv´ aˇrej´ı pr´ azdnou skupinu radiobutton˚ u. Nejpouˇz´ıvanˇejˇs´ı metody pˇri pr´ aci s tˇr´ıdou ButtonGroup. Metoda
Popis
add(AbstractButton b)
Pˇrid´ an´ı tlaˇ c´ıtka do skupiny.
remove(AbstractButton b)
Odstranˇ en´ı tlaˇ c´ıtka ze skupiny.
getButtonCount()
Zjist´ı poˇ cet kompnent ve skupinˇ e.
getSelection()
Vrac´ı odkaz na zvolen´ e tlaˇ c´ıtko.
isSelected(ButtonModel m)
Z´ısk´ an´ı stavu tlaˇ c´ıtka.
setSelected(ButtonModel m, boolean status)
Nastaven´ı stavu tlaˇ c´ıtka.
Tabulka 10.7: Pˇrehled metod tˇr´ıdy JButtonBroup.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Pˇri zmˇenˇe stavu radiobuttonu je generov´ ana ud´ alost, kterou lze odchytit prostˇrednictv´ı rozhran´ı ItemListener za pouˇzit´ı metody itemStateChanged(). Pr´ aci s radiobuttony si uk´ aˇzeme na n´ asleduj´ıc´ım pˇr´ıkladu: na formul´ aˇri bude trojice radiobutton˚ u sdruˇzen´ ych v buttongroup a jeden label informuj´ıc´ı, kter´e tlaˇc´ıtko bylo stlaˇceno. Nov´e radiobuttony vytvoˇr´ıme pomoc´ı konstrukce JRadioButton rb1=new JRadioButton("Prvni"); JRadioButton rb2=new JRadioButton("Druhy"); JRadioButton rb3=new JRadioButton("Treti"); Poˇzadujeme, aby mohlo b´ yt stisknuto pouze jedno z tˇechto tlaˇc´ıtek. Vytvoˇr´ıme proto nov´ y buttongroup a pˇrid´ ame do nˇej vytvoˇren´e radiobuttony. ButtonGroup bm=new ButtonGroup(); bm.add(rb1); bm.add(rb2); bm.add(rb3); V´ ysledek vypad´ a takto
Obr´ azek 10.28: Pr´ ace s radio buttony. Zdrojov´ y k´ od k pˇr´ıkladu. public class Radiobuttony extends JFrame { private JRadioButton rb1, rb2, rb3; private JLabel l; public Radiobuttony(int vyska, int sirka) { this.setSize(vyska, sirka); this.setTitle("Radiobuttony"); rb1=new JRadioButton ("Prvn´ ı"); rb2=new JRadioButton ("Druhy"); rb3=new JRadioButton ("Treti"); l=new JLabel(); this.getContentPane().add(rb1); this.getContentPane().add(rb2); this.getContentPane().add(rb3); this.getContentPane().add(l);
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E this.setLayout(new GridLayout(4,1)); rb1.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { rb1Changed(e); } }); rb2.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { rb2Changed(e); } }); rb3.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { rb3Changed(e); } }); } public void rb1Changed(ItemEvent e) { if(rb1.isSelected()) l.setText("Prvni"); } public void rb2Changed(ItemEvent e) { if(rb2.isSelected()) l.setText("Druhy"); } public void rb3Changed(ItemEvent e) { if(rb3.isSelected()) l.setText("Treti"); } } 10.1.8.5
JTextField
Komponenta pˇredstavuje editaˇcn´ı pol´ıˇcko, do kter´eho mohou b´ yt zad´ av´ any jednoˇr´ adkov´e u ´daje z kl´ avesnice. Potvrzen´ı u ´daj˚ u je provedeno stiskem kl´ avesy Enter. Zad´ avan´ y text m˚ uˇze b´ yt delˇs´ı neˇz ˇs´ıˇrka JTextFieldu. Komponenta se pouˇz´ıv´ a, pokud potˇrebujeme od uˇzivatele z´ıskat vstupn´ı u ´daje nutn´e pro bˇeh programu. Kaˇzd´ y text field by mˇel b´ yt pops´ an pomoc´ı labelu tak, aby jeho v´ yznam byl jasn´ y (v programu by se nemˇely vyskytovat nepopsan´e text fieldy). K dispozici jsou n´ asleduj´ıc´ı konstruktory. JTextField(); JTextField(String text); Prvn´ı konstruktor vytvoˇr´ı pr´ azdn´ y textfield, druh´ y konstruktor textfield obsahuj´ıc´ı zadan´ y text. Pˇrehled ˇcasto pouˇz´ıvan´ ych metod komponenty JTextField.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Metoda
Popis
setText(String text)
Nastaven´ı popisu.
getText()
Z´ısk´ an´ı popisu.
setEditable(bool b)
Nastaven´ı, zda komponenta je/nen´ı read only.
Tabulka 10.8: Pˇrehled metod tˇr´ıdy JBTextField. Po stisku kl´ avesy Enter je generov´ ana ud´ alost, kterou lze odchytit prostˇrednictv´ı rozhran´ı ActionListener za pouˇzit´ı metody actionPerformed(). Pr´ ace s JTextFieldem bude ilustrov´ ana na pˇr´ıkladu, kdy do dvou vygenerovan´ ych text field˚ u zad´ ame ˇc´ısla, jejich souˇcet bude zobrazen v JLabelu. Za pouˇzit´ı metody setText() inicializujeme v´ ychoz´ı hodnoty v textfieldech na 0. public class Textfieldy extends JFrame { private double prvni,druhe,soucet; private JLabel l1,l2,l3; private JTextField t1, t2; private JButton b; public Textfieldy(int vyska, int sirka) { this.setSize(vyska,sirka); this.setTitle("Scitani cisel"); this.setLayout(new GridLayout(3,2)); l1=new JLabel("Prvni cislo"); l2=new JLabel("Druhe cislo"); t1=new JTextField(); t2=new JTextField(); t1.setText("0"); t2.setText("0"); b=new JButton("Soucet"); l3=new JLabel(); this.getContentPane().add(l1); this.getContentPane().add(l2); this.getContentPane().add(t1); this.getContentPane().add(t2); this.getContentPane().add(b); this.getContentPane().add(l3); this.setVisible(true); t1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { prvniZadej(e); } }); t2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { druheZadej(e); } });
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { soucet(e); } }); } public void prvniZadej(ActionEvent e) { this.prvni=Integer.parseInt(t1.getText()); } public void druheZadej(ActionEvent e) { this.druhe=Integer.parseInt(t2.getText()); } public void soucet(ActionEvent e) { soucet=this.prvni+this.druhe; l3.setText(String.valueOf(soucet)); } } Pouˇ zit´ı ud´ alosti FocusLost Pohodlnˇejˇs´ı pro uˇzivatele by bylo, kdyby po zad´ an´ı nebyl nucen potvrzovat hodnotu stiskem kl´ avesy Enter. Pokud bychom u obou text field˚ u neoˇsetˇrovali ud´ alost ActionEvent ale FocusLost, odpadlo by potvrzov´ an´ı. Vyuˇzijeme rozhran´ı FocusListener. Tento pˇr´ıstup je bˇeˇznˇe vyuˇz´ıv´an v praxi. Vˇsimnˇeme si, ˇze mus´ıme pˇredefinovat i druhou metodu, focusGained(). t1.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { prvniZadej(e); } public void focusGained(FocusEvent e) {}; }); t2.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { druheZadej(e); } public void focusGained(FocusEvent e){}; }); V´ ysledek vypad´ a takto.
Obr´ azek 10.29: Souˇcet dvojice ˇc´ısel s pouˇzit´ım JTextField˚ u.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Metoda
Popis
addItem(Object o)
Pˇrid´ an´ı poloˇ zky do seznamu na posledn´ı pozici.
insertItem(Object o, int
Pˇrid´ an´ı poloˇ zky do seznamu na
position)
uvedenou pozici.
getItem()
Z´ısk´ an´ı poloˇ zky na poˇ zadovan´ e pozici.
getSelectedItem()
Z´ısk´ an´ı oznaˇ cen´ e poloˇ zky.
removeAllItems()
Odstranˇ en´ı vˇsech poloˇ zek seznamu.
removeItemAt(int position)
Odstranˇ en´ı poˇ zadovan´ e poloˇ zky seznamu.
getItemCount()
Poˇ cet poloˇ zek seznamu.
getSelectedIndex()
Index oznaˇ cen´ e poloˇ zky.
setSelectedIndex()
Oznaˇ cen´ı poˇ zadovan´ e poloˇ zky seznamu.
setEditable(boolean b)
Nastaven´ı, zda poloˇ zky combo boxu mohou b´ yt editovateln´ e.
Tabulka 10.9: Pˇrehled metod tˇr´ıdy JButton. 10.1.8.6
JComboBox
Komponenta JComboBox pˇredstavuje rozbalovac´ı seznam. Seznam je tvoˇren jednotliv´ ymi poloˇzkami setˇr´ıdˇen´ ych podle pˇredem zn´ am´eho kl´ıˇce. Viditeln´ a je pouze jedna ˇr´ adka, po kliknut´ı na ˇsipku se seznam rozbal´ı a umoˇzn´ı zvolit kliknut´ım nˇekterou z poloˇzek seznamu. Pouˇzit´ı je podobn´e jako v pˇr´ıpadˇe radio button˚ u, komponenta je vhodn´ a pro v´ ybˇer z vˇetˇs´ıho mnoˇzstv´ı variant. V takov´em pˇr´ıpadˇe pˇri pouˇzit´ı radio button˚ u vznikaj´ı okna pˇr´ıliˇs velk´ ych rozmˇer˚ u, na kter´e se pak jiˇz nevejdou dalˇs´ı komponenty. Combo boxy mohou m´ıt pomˇernˇe odliˇsn´ y vzhled i zp˚ usob pr´ ace s nimi. Jejich poloˇzky mohou b´ yt editovateln´e popˇr. lze poloˇzky pˇrid´ avat i za bˇehu programu. My se budeme zab´ yvat nejbˇeˇznˇejˇs´ı variantou-needitovateln´ ymi combo boxy. Poloˇzky combo boxu jsou ˇc´ıslov´ any, lze k nimi pˇristupovat za pouˇzit´ı indexu; prvn´ı poloˇzka m´a index 0. Tˇr´ıda m´ a k dispozici nˇekolik konstruktor˚ u JComboBox(); JComboBox(Object o); JComboBox(BVector v); Prvn´ı konstruktor vytvoˇr´ı pr´ azdn´ y combo box, druh´ y naplnˇen´ y poloˇzkami pˇredstavovan´ ymi objekty tˇr´ıdy Object, tˇret´ı naplnˇen´ y poloˇzkami z dynamick´e datov´e struktury vector. Pˇrehled ˇcasto pouˇz´ıvan´ ych metod komponenty JComboBox nalezneme v n´ asleduj´ıc´ı tabulce. Pˇri pr´ aci s combo boxem je nejˇcastˇeji pouˇz´ıv´ ano rozhran ActionListener. Metoda actionPerformed() je vyvol´ ana v okamˇziku, kdy uˇzivatel zvol´ı nˇekterou z poloˇzek combo boxu nebo po editaci nˇekter´e poloˇzky stiskne kl´ avesu Enter. Uprav´ıme pˇr´ıklad pracuj´ıc´ı s radio buttony, m´ısto radiobuttonu pouˇzijeme combo box. Uk´ azka zdrojov´eho k´ odu. public class Comboboxy extends JFrame { private JLabel l; private JComboBox c; public Comboboxy(int vyska, int sirka) {
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E this.setSize(vyska, sirka); this.setTitle("ComboBox"); c=new JComboBox(); c.addItem("Prvni"); c.addItem("Druhy"); c.addItem("Treti"); l=new JLabel(); this.getContentPane().add(c); this.getContentPane().add(l); this.setLayout(new FlowLayout()); c.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { cVyber(e); } }); this.setVisible(true); } public void cVyber(ActionEvent e) { l.setText(c.getSelectedItem().toString()); } } V´ ysledek vypad´ a takto.
Obr´ azek 10.30: Pr´ ace s JComboBoxem. 10.1.8.7
JList
Jedn´ a se o v´ıceˇr´ adkovou komponentu pˇredstavuj´ıc´ı seznam. Na rozd´ıl od JComboBoxu umoˇzn ˇuje trvale zobrazit cel´ y seznam a nejen pouze jednu jeho poloˇzku. V pˇr´ıpadˇe, ˇze je d´elka seznamu vˇetˇs´ı neˇz d´elka komponenty nebo ˇs´ıˇrka poloˇzky vˇetˇs´ı neˇz ˇs´ıˇrka komponenty, pro listov´ an´ı jsou pouˇzity scrollbary. V´ ybˇ er ze seznamu. Pro v´ ybˇer ze seznamu je pouˇz´ıv´ ana instance tˇr´ıdy ListSelectionModel. V´ ybˇer ze seznamu lze prov´ adˇet tˇremi zp˚ usoby: • V´ ybˇer jedn´e poloˇzky • V´ ybˇer souvisl´eho intervalu v´ıce poloˇzek • V´ ybˇer nesouvisl´eho intervalu v´ıce poloˇzek. Nejˇcastˇeji je pouˇz´ıv´ ana prvn´ı varianta. Zp˚ usob v´ ybˇeru lze nastavit metodou setSelectionMode(int const) za poˇzit´ı jedn´e ze tˇr´ı n´ıˇze uveden´ ych konstant: SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION, MULTIPLE_INTERVAL_SELECTION. Uk´ azky variant v´ ybˇer˚ u nalezneme na n´ asleduj´ıc´ım obr´ azku.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.31: Vlevo jednoduch´y v´ybˇer, uprostˇred souvisl´y v´ybˇer, vpravo nesouvisl´y v´ybˇer. Tˇr´ıda m´ a k dispozici nˇekolik konstruktor˚ u, uvedeme: JList(); JList(vector v); Prvn´ı konstruktor vytvoˇr´ı pr´ azdn´ y seznam, druh´ y seznam naplnˇen´ y poloˇzkami vectoru. Pˇ rid´ av´ an´ı poloˇ zek do seznamu.
Pˇrid´ av´ an´ı poloˇzek do seznamu je moˇzn´e prov´ adˇet dvˇema zp˚ usoby.
• S pouˇzit´ım modelu. • Bez pouˇzit´ı modelu. V dalˇs´ım v´ ykladu naznaˇc´ıme struˇcnˇe obˇe varianty. Tˇr´ıda JList obsahuje mnoho metod, pˇrehled nejˇcastˇeji pouˇz´ıvan´ ych nalezneme v n´ asleduj´ıc´ı tabulce. Metoda
Popis
addElement(Object o)
Pˇrid´ an´ı poloˇ zky do seznamu (s vyuˇ zit´ım modelu). Pˇrid´ an´ı poloˇ zky do seznamu (bez vyuˇ zit´ı
add(Component c)
modelu). setVisibleRowCount(int rows)
Nastaven´ı poˇ ctu souˇ casnˇ e viditeln´ ych ˇr´ adek seznamu.
getVisibleRowCount()
Z´ısk´ an´ı poˇ ctu souˇ casnˇ e viditeln´ ych ˇr´ adek seznamu.
setSelectedMode(ListModel l)
Nastaven´ı zp˚ usobu v´ ybˇ eru poloˇ zek na jednu ze tˇr´ı v´ yˇse uveden´ ych.
setSelectedIndex(int)
Nastaven´ı vybran´ e poloˇ zky seznamu.
setSelectedIndices(int[])
Nastaven´ı v´ıce vybran´ ych poloˇ zek seznamu.
getSelectedIndex()
Index vybran´ e poloˇ zky v seznamu.
int[] getSelectedIndices()
Index vybran´ ych poloˇ zek seznamu uloˇ zen´ yv poli.
getSelectedValues()
Vrac´ı seznam vˇsech oznaˇ cen´ ych hodnot.
setListData(Object o)
Do seznamu vloˇ z´ı poˇ zadovan´ a data.
clearSelection()
Smaz´ an´ı vˇsech smazan´ ych poloˇ zek seznamu.
removeAll()
Smaz´ an´ı vˇsech poloˇ zek seznamu.
isSelectionEmpty()
Zjist´ı, zda byla vybr´ ana nˇ ejak´ a poloˇ zka.
Tabulka 10.10: Pˇrehled metod tˇr´ıdy JList. Pˇri pr´ aci se seznamy jsou pouˇz´ıv´ ana dvˇe rozhran´ı ActionListener a ItemListener. Ud´ alost ItemEvent je generov´ ana pˇri jednom kliknut´ı na poloˇzku seznamu, ud´ alost ActionEvent pˇri dvojkliku na nˇekterou z poloˇzek seznamu.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E V n´ asleduj´ıc´ım pˇr´ıkladu vytvoˇr´ıme dva seznamy. V druh´em seznamu budou zn´ azornˇeny vˇsechny poloˇzky, kter´e budou v prvn´ım seznamu zv´ yraznˇeny. V tomto pˇr´ıpadˇe budeme tedy pro JList pouˇz´ıvat rozhran´ı ItemListener (na poloˇzky nebudeme klikat dvojklikem, ale pouze je vyb´ırat). Pˇ rid´ an´ı dat do seznamu s pouˇ zit´ım modelu. V tomto pˇr´ıpadˇe vyuˇz´ıv´ ame rozhran´ı ListModel. Jeho implementac´ı je tˇr´ıda DefaultListModel, kter´ a disponuje nˇekolika metodami pro pr´ aci s modelem. V prvn´ım kroku vytvoˇr´ıme instanci tˇr´ıdy DefaultListModel. DefaultListModel lm=new DefaultListModel(); dalˇs´ım kroku pouˇzijeme metodu addElement() a pˇrid´ ame do modelu pˇet prvk˚ u. lm.addElement("Prvni polozka"); lm.addElement("Druha polozka"); lm.addElement("Treti polozka"); lm.addElement("Ctvrta polozka"); lm.addElement("Pata polozka"); Vytvoˇr´ıme novou instanci tˇr´ıdy JList (v naˇsem pˇr´ıpadˇe dvˇe) a metodou setSelectionMode nastav´ıme zp˚ usob v´ ybˇeru poloˇzek v komponentˇe. l1=new JList(); l2=new JList(); l1.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); l2.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); Vytvoˇren´ y model n´ aslednˇe “spoj´ıme“ se seznamem. l1.setModel(lm); Mohli bychom pouˇz´ıt i explicitn´ı konstruktor l1=new JList(lm); Pˇ rid´ an´ı dat do seznamu bez pouˇ zit´ı modelu Nejprve vytvoˇr´ıme stejnˇe jako v pˇredchoz´ım pˇr´ıpadˇe obˇe instance tˇr´ıdy JList. Pˇrid´ an´ı poloˇzek do seznamu provedeme takto: lm.add("Prvni"); lm.add("Druhy"); lm.add("Treti"); lm.add("Ctvrty"); lm.add("Paty"); Dalˇs´ı postup bude v obou pˇr´ıpadech stejn´ y. V handleru obsluhuj´ıc´ım ud´ alost ActionEvent zjist´ıme metodou getSelectedValues() vˇsechny zv´ yraznˇen´e poloˇzky a za pouˇzit´ı metody setListData(Object o) je nastav´ıme druh´emu seznamu.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E public void cPrevod(ActionEvent e) { Object [] o=l1.getSelectedValues(); l2.setListData(o); } V´ ysledek vypad´ a takto.
Obr´ azek 10.32: Pr´ ace se seznamem. Uk´ azka zdrojov´eho k´ odu: public class Lists extends JFrame { private JList l1, l2; private JButton b; public Lists(int vyska, int sirka) { this.setSize(vyska, sirka); this.setTitle("List"); l1=new JList(); l2=new JList(); JScrollPane sp = new JScrollPane(l1, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); DefaultListModel lm=new DefaultListModel(); lm.addElement("Prvni polozka"); lm.addElement("Druha polozka"); lm.addElement("Treti polozka"); lm.addElement("Ctvrta polozka"); lm.addElement("Pata polozka"); b=new JButton("Napln"); l1.setModel(lm); JScrollPane sp2 = new JScrollPane(l2, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); this.getContentPane().add(l1); this.getContentPane().add(b); this.getContentPane().add(l2);; this.setLayout(new FlowLayout()); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { cPrevod(e);
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E } }); this.setVisible(true); } public void cPrevod(ActionEvent e) { Object [] o=l1.getSelectedValues(); l2.setListData(o); } } Scrollov´ an´ı seznamem. Pokud je seznam dlouh´ y, je vhodn´ y umoˇznit jeho scrollov´ an´ı, tj. posunov´an´ı obsahu seznamu prostˇrednictv´ım komponenty JScrollPane. Scrollov´ an´ı m˚ uˇze b´ yt jak vodorovn´e, tak svisl´e. Komponenta m´ a nˇekolik konstruktor˚ u, z nichˇz nejˇcastˇeji je pouˇz´ıv´ an tento JScrollPane(Component c, int vertical, int horizontal); Je vytvoˇren nov´ y scrollovac´ı panel scrolluj´ıc´ı obsahem zadan´e komponenty ve smˇeru horizont´ aln´ım, vertik´aln´ım, obou ˇci ˇz´ adn´em na z´ akladˇe hodnot promˇenn´ ych vertical a horizontal. Ty mohou nab´ yvat n´ asleduj´ıc´ıch hodnot. Poloˇ zka
Popis
HORIZONTAL_SCROLLBAR_ALLWAYS
Vodorovn´ y posuvn´ık vˇ zdy.
HORIZONTAL_SCROLLBAR_AS_NEEDED
Vodorovn´ y posuvn´ık jen kdyˇ z jepotˇreba.
HORIZONTAL_SCROLLBAR_NEVER
Vodorovn´ y posuvn´ık nikdy
VERTICAL_SCROLLBAR_ALLWAYS
Svisl´ y posuvn´ık vˇ zdy.
VERTICAL_SCROLLBAR_AS_NEEDED
Svisl´ y posuvn´ık jen kdyˇ z je potˇreba.
VERTICAL_SCROLLBAR_NEVER
Svisl´ y posuvn´ık nikdy.
Tabulka 10.11: Pˇrehled metod tˇr´ıdy JScrollPane. Vytvoˇr´ıme nov´ y scrollovac´ı panel, kter´ y bude pohybovat obsahem seznamu v obou smˇerech. V´ ysledek bude vypadat takto. JScrollPane sp1 = new JScrollPane(l1, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); dalˇs´ım kroku jiˇz nesm´ıme na ContentPane formul´ aˇre pˇridat seznam, ale jen novˇe vytvoˇren´ y scrollovac´ı panel. Stejn´ ym zp˚ usobem postupujeme i v pˇr´ıpadˇe druh´eho ListBoxu. JScrollPane sp1 = new JScrollPane(l1, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); JScrollPane sp2 = new JScrollPane(l2, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); this.getContentPane().add(sp1); this.getContentPane().add(b); this.getContentPane().add(sp2);
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Komponenty s posuvn´ıky vypadaj´ı “estetiˇctˇeji”.
Obr´ azek 10.33: Pouˇzit´ı posuvn´ık˚ u pˇri pr´ aci se seznamem.
10.1.8.8
JTable
Komponenta pˇredstavuje tabulku, ˇcasto se pouˇz´ıv´ a pro zobrazov´ an´ı v´ ysledk˚ u v´ ypoˇct˚ u, v´ ypisu seznam˚ u ˇci zad´ av´ an´ı vstupn´ıch dat. Data v tabulce mohou, ale nemus´ı b´ yt, editovateln´ a. S tabulkou se zpravidla pracuje za pouˇzit´ı dvojice model˚ u. Prvn´ı model je pouˇz´ıv´ an pro sloupce (z ˇcasov´eho hlediska se mu nebudeme vˇenovat), druh´ y model pro celou tabulku. Model sloupce ovlivˇ nuje zp˚ usob zobrazen´ı dat ve sloupci ˇci moˇznosti jejich editace, model tabulky disponuje ˇradou metod pro pr´ aci s vlastn´ı tabulkou. Moˇznosti pr´ ace s tabulkami jsou v Javˇe velmi rozs´ ahl´e (nˇekter´e pas´ aˇze jsou pomˇernˇe obt´ıˇzn´e a komplikovan´e), uvedeme pouze nejd˚ uleˇzitˇejˇs´ı informace. K dispozici je nˇekolik konstruktor˚ u JTable (); JTable (int rows,int columns); JTable (TableModel t); JTable(Object[][] data, Object[] column_names) JTable(Vector row_data, Vector column_names) Prvn´ı z konstruktor˚ u vytvoˇr´ı pr´ azdnou tabulku, druh´ y pr´ azdnou tabulku se zadan´ ym poˇctem ˇr´ adk˚ u a sloupc˚ u, ˇ tˇret´ı tabulku naplnˇenou komponentami z instance tˇr´ıdy TableModelu. Ctvrt´ y a p´ at´ y konstruktor vytvoˇr´ı tabulku naplnˇenou daty, vˇcetnˇe n´ azv˚ u sloupc˚ u. Vˇsechny poloˇzky tabulky jsou editovateln´e, jednotliv´e prvky tabulky mus´ı b´ yt uloˇzeny v dynamick´e datov´e struktuˇre pˇredstavovan´e vektorem. Pˇ rid´ an´ı tabulky na JScrollPane. Pˇri pr´ aci s rozs´ ahl´ ymi tabulkami je vhodn´e prov´est jejich pˇrid´an´ı na JScrollPane. Uˇcin´ıme to podobn´ ym zp˚ usobem jako v pˇr´ıpadˇe seznam˚ u. ScrollPane sp = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); Implementace modelu. Chceme -li vytvoˇrit vlastn´ı model tabulky, pouˇzijeme abstraktn´ı tˇr´ıdu AbstractTableModel. Astraktn´ı metody tˇr´ıdy je nutn´e pˇredefinovat, m˚ uˇzeme tak ovlivnit jejich funkˇcnost podlem potˇreby. V tomto pˇr´ıpadˇe je nutn´e pˇredefinovat n´ asleduj´ıc´ı trojici metod: getRowCount(), getColumnCount() a getValueAt(). D´ ale je vhodn´e pˇredefinovat metodu getColumnName() vracej´ıc´ı jm´eno sloupce. Chceme -li tabulku n´ aslednˇe editovat, mus´ıme pˇret´ıˇzit metody setValueAt(int row,int column) a isCellEditable(bool status). Pˇri zmˇenˇe dat je nutn´e tuto informaci poskytnout vˇsem zaregistrovan´ ym posluchaˇc˚ um. Pro jednoduˇsˇs´ı pˇr´ıpady, kdy vystaˇc´ıme s v´ ychoz´ı implementac´ı, je vhodnˇejˇs´ı pouˇz´ıt tˇr´ıdu DefaultTableModel. Jednotliv´e ˇr´ adky jsou ukl´ ad´ any do dynamick´e struktury Vector. Model umoˇzn ˇuje automatick´e generov´an´ı ud´ alost´ı pˇri zmˇenˇe dat uˇzivatelem, buˇ nky tabulky lze tedy editovat.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Vytvoˇ ren´ı tabulky. V pˇr´ıkladu vˇenovan´em pr´ aci s tabulkou vytvoˇr´ıme tˇr´ıdu, kter´ a je potomkem abstraktn´ı tˇr´ıdy AbstractTableModel. Tabulka bude tvoˇrena 5 sloupci, kter´e budou zobrazovat mocniny ˇc´ısel prvn´ıch pˇet ˇclen˚ u aritmetick´ ych posloupnost´ı ˇc´ısel 1-5. Tˇr´ıdu nazveme Tabulka. Obsah tabulky tvoˇr´ı poloˇzky 2D pole typu Object, sloupce poloˇzky pole typu String. Deklarujeme odkazy na tyto promˇenn´e jako datov´e poloˇzky tˇr´ıdy. public class Tabulka extends AbstractTableModel{ private Object [][] data; String [] sloupce; .... } Jejich inicializaci provedeme v konstruktoru. Konstruktor bude explicitn´ı, abychom mu mohli pˇredat poˇcet ˇr´ adek a sloupc˚ u takto vytvoˇren´e tabulky. public Tabulka(int rows, int columns) { data=new Object[rows][columns]; sloupce=new String[columns]; ... } Generov´ an´ı posloupnosti provedeme ve speci´ aln´ı metodˇe nazvan´e getPosloupnost(), popis sloupc˚ u v metodˇe Sloupce(). Obˇe metody budou vykon´ any v konstruktoru. public Tabulka(int rows, int columns) { data=new Object[rows][columns]; sloupce=new String[columns]; this.Sloupce(); this.getPosloupnost(); } Zdrojov´ y k´ od metod vypad´ a takto. public void getPosloupnost() { for (int i=0;i
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Nyn´ı provedeme pˇredefinov´ an´ı vˇsech v´ yˇse uveden´ ych abstraktn´ıch metod tˇr´ıdy AbstractTableModel tak, aby poskytovaly pouˇziteln´e v´ ysledky. public public public return }
int getRowCount() {return data.length;} int getColumnCount() {return data[0].length;} Object getValueAt(int rowIndex, int columnIndex) { data[rowIndex][columnIndex];
V´ ysledek vypad´ a takto.
Obr´ azek 10.34: Tabulka se z´ ahlav´ım sloupc˚ u naplnˇen´ a hodnotami.
Nastaven´ı ˇ s´ıˇ rky sloupc˚ u. U tabulky ˇcasto potˇrebujeme nastavit r˚ uzn´e ˇs´ıˇrky sloupc˚ u v z´ avislosti na typu ˇıˇrka je zad´ zobrazovan´ ych dat. K tomuto u ´ˇcelu slouˇz´ı metoda setPreferredWidth(int sirka). S´ av´ana v pixelech. Metoda je vol´ ana pro konkr´etn´ı sloupec z´ıskan´ y metodou getColumn(int index). t.getColumnModel().getColumn(0).setPreferredWidth(50); Mˇenit ˇs´ıˇrku sloupc˚ u je t´eˇz moˇzno prov´ adˇet prostˇrednictv´ım myˇsi. Povolit ˇci zak´ azat tuto moˇznost lze prov´est prostˇrednictv´ım metody setAutoResizeMode(int mode). M´ od
Popis
AUTO_RESIZE_SUBSEQUENT_COLUMNS
Zmˇ ena ˇs´ıˇrky sloupce tabulky, nem´ a
AUTO_RESIZE_NEXT_COLUMN
Zmˇ ena ˇs´ıˇrky sloupce na u ´kor ˇs´ıˇrky n´ asleduj´ıc´ıho sloupce.
AUTO_RESIZE_ALL_COLUMNS
Zmˇ ena ˇs´ıˇrky sloupce ovlivn´ı ˇs´ıˇrku vˇsech ostatn´ıch sloupc˚ u.
AUTO_RESIZE_LAST_COLUMN
Zmˇ ena ˇs´ıˇrky sloupce na u ´kor ˇs´ıˇrky pˇredchoz´ıho sloupce. ˇıˇrku sloupce nen´ı moˇ S´ zn´ e mˇ enit.
vliv na sousedn´ı sloupce.
AUTO_RESIZE_OFF
Tabulka 10.12: M´ ody zmˇeny ˇs´ıˇrky sloupc˚ u u tabulky.
V´ ybˇ er ˇ r´ adk˚ u tabulky. V tabulce je moˇzno oznaˇcovat (tj. vyb´ırat) ˇr´ adky, se kter´ ymi m˚ uˇzeme v dalˇs´ıch kroc´ıch prov´ adˇet r˚ uzn´e manipulace. Existuj´ı tˇri moˇznosti v´ ybˇeru (shodn´e s komponentou JList), lze je nastavit metodou setSelectionMode(). Detekci ˇr´ adky/ˇr´ adek, kter´e byly vybr´ any, lze prov´est s vyuˇzit´ım instance tˇr´ıdy ListSelectionModel. Vytvoˇr´ıme instanci tˇr´ıdy ListSelectionModel, kterou inicializujeme prostˇrednictv´ım metody getSelectionModel(). ListSelectionModel vyber=t.getSelectionModel();
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Pˇri v´ ybˇeru ˇr´adky doch´ az´ı k ud´ alosti ListSelection, pro pr´ aci s n´ı vyuˇzijeme rozhran´ı ListSelectionListener. Zaregistrujeme posluchaˇce vyber.addListSelectionListener(new ListSelectionListener()); a n´ aslednˇe implementujeme abstraktn´ı metody rozhran´ı. V metodˇe vytvoˇr´ıme inicializujeme odkaz tˇr´ıdy ListSelectionModel aktu´ aln´ım modelem za pouˇzit´ı metody getSource(). Na nˇej n´ aslednˇe aplikujeme metodu isSelectionEmpty() sdˇeluj´ıc´ı, zda je v´ ybˇer pr´ azdn´ y. Pokud nen´ı, z´ısk´ ame vybranou ˇr´ adku metodou getMinSelectionIndex(). Postup je, jak vid´ıme, pomˇ ernˇe komplikovan´ y. int radka; vyber.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { int radka; ListSelectionModel ls=(ListSelectionModel) e.getSource(); if (!l.isSelectionEmpty()) radka=ls.getMinSelectionIndex() } });
ˇ ıslo vybran´e ˇr´ C´ adky sdˇel´ıme v JLabelu, kter´ y na formul´ aˇr pˇrid´ ame. K´ od uprav´ıme, v´ ysledek vypad´ a takto: public class Tabulky3 extends JFrame{ private int radka; private JLabel l; public Tabulky3(int width, int height) { this.setSize(width, height); this.setTitle("Tabulky"); l=new JLabel(); TableModel tm=new TabulkyDataAbstract(5,5); JTable t=new JTable(tm); this.setLayout(new GridLayout(1,2)); JScrollPane sp = new JScrollPane(t,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); this.getContentPane().add(l); t.getColumnModel().getColumn(0).setPreferredWidth(50); ListSelectionModel vyber = t.getSelectionModel(); t.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); vyber.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { ListSelectionModel ls=(ListSelectionModel) e.getSource(); if (!ls.isSelectionEmpty()) { radka=ls.getMinSelectionIndex(); l.setText("Vybrany radek:"+String.valueOf(radka+1)); } } }); t.setAutoResizeMode(t.AUTO_RESIZE_SUBSEQUENT_COLUMNS); this.getContentPane().add(sp); this.setVisible(true); } }
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E V´ ysledek vypad´ a takto.
Obr´ azek 10.35: V´ybˇer ˇr´ adku tabulky. Detekce zmˇ en v tabulce. Chceme -li detekovat zmˇeny v tabulce, pouˇzijeme rozhran´ı TableModelListener. Rozhran´ı implementuje jednu metodu a to tableChanged(). Tuto metodu mus´ıme pˇredefinovat. t.getModel().addTableModelListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { } }); Sloupec, ve kter´em se upravovan´ a buˇ nka nach´ az´ı, m˚ uˇzeme detekovat prostˇrednictv´ım metody getColumn(), ˇr´ adek, ve kter´em se upravovan´ a buˇ nka nach´ az´ı, prosˇrednictv´ım metody getRow(). Upravenou hodnotu lze z´ıskat prostˇrednictv´ım metody getValueAt(int row, int column). public void tableChanged(TableModelEvent e) { int radek = e.getRow(); int sloupec = e.getColumn(); TableModel m = (TableModel)e.getSource(); Object data = model.getValueAt(row, column) } Dalˇs´ı operace s JTable jiˇz nebudeme uv´ adˇet, lze je nal´ezt ve specializovan´e literatuˇre. Pˇrehled nejpouˇz´ıvanˇejˇs´ım metod u komponenty JTable. 10.1.8.9
Dialogov´ a okna
Pokud potˇrebujeme v aplikaci vytvoˇrit nˇejak´e dalˇs´ı okno, zpravidla k tomu nepouˇz´ıv´ ame tˇr´ıdu JFrame. Jak jsme uv´ adˇeli v´ yˇse, aplikace by mˇela disponovat jedn´ım framem. Ostatn´ı okna jsou vytv´ aˇrena formou dialogu. Pr´ ace s dialogy je podobn´ a jako s framy. Dialogov´ a okna dˇel´ıme do dvou z´ akladn´ıch skupin: • Mod´ aln´ı okna. • Nemod´ aln´ı okna. Mod´ aln´ı okno je takov´e okno, kter´e pˇri otevˇren´ı z˚ ust´ av´ a neust´ ale navrchu, pˇrekryje vˇsechna ostatn´ı okna aplikace. Dokud nen´ı uzavˇreno, znemoˇzn ˇuje pr´ aci s jin´ ymi okny aplikace. Mod´ aln´ı okna se ˇcasto pouˇz´ıvaj´ı pro dialogy. Nemod´ aln´ı okna tuto vlastnost nemaj´ı, lze s nimi pracovat bez omezen´ı. Pr´ ace s dialogy je podobn´ a pr´ aci s formul´ aˇri. Dialogy jsou vhodn´e pro nastavov´ an´ı parametr˚ u programu, umoˇzn ˇuj´ı uˇzivateli zareagovat na ˇcinnost programu, informuj´ı ho o aktu´ aln´ım stavu programu. Dialogy lze navrhovat dle vlastn´ı potˇreby, m˚ uˇzeme vˇsak vyuˇz´ıvat nˇekter´e standardizovan´e dialogy.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Metoda
Popis
getRowCount()
Z´ısk´ an´ı poˇ ctu ˇr´ adk˚ u tabulky.
getColumnCount()
Z´ısk´ an´ı poˇ ctu sloupc˚ u tabulky.
getValueAt(int row, int column)
Z´ısk´ an´ı hodnoty v zadan´ em ˇr´ adku a sloupci.
getColumnName(int column)
Z´ısk´ an´ı n´ azvu sloupce.
isCellEditable(int row, int column)
Je hodnota v zadan´ em ˇr´ adku a sloupci editovateln´ a.
setPreferredWith(int width)
Nastaven´ı poˇ zadovan´ e ˇs´ıˇrky sloupce v pixelech.
getColumn(Object o)
Vrac´ı instanci typu TableColumn.
setAutoResizeMode(int mode)
Nastaven´ı m´ odu zmˇ eny ˇs´ıˇrky sloupce myˇs´ı.
setSelectionMode(int mode)
Nastaven´ı moˇ znosti v´ ybˇ eru ˇr´ adek u tabulky (jedna, v´ıce,..)
getEditingRow()
Vrac´ı ˇ c´ıslo ˇr´ adky, kter´ a je editov´ ana.
getEditingColumn()
Vrac´ı ˇ c´ıslo sloupce, kter´ y je editov´ an.
setEditingRow()
Nastav´ı ˇ c´ıslo ˇr´ adky, kter´ a bude editov´ ana.
setEditingColumn()
Nastav´ı ˇ c´ıslo sloupce, kter´ y bude editov´ an.
setModel()
Nastaven´ı modelu pro tabulku.
Tabulka 10.13: Pˇrehled metod tˇr´ıdy JTable. Pˇ reddefinovan´ e dialogy. V knihovnˇe Swing lze nal´ezt ˇradu pˇreddefinovan´ ych dialog˚ u. Tˇr´ıda JOptionPane obsahuje statick´e metody, prostˇrednictv´ım kter´ ych lze dialogy vyvol´ avat. Pod´ıv´ ame se na nejˇcastˇeji pouˇz´ıvan´e dialogy. ShowMessageDialog. Tento mod´ aln´ı dialog slouˇz´ı ke sdˇelov´ an´ı zpr´ av a d˚ uleˇzit´ ych informac´ı ve smˇeru program->uˇzivatel. Je nejjednoduˇsˇs´ım dialogem, zobrazuje jedin´e tlaˇc´ıtko s popisem OK. Vzhled dialogu m˚ uˇze b´ yt r˚ uznˇe modifikov´ an, metoda JOptionPane.showMessageDialog() je pˇret´ıˇzena. Pouˇzijeme -li JOptionPane.showMessageDialog(JComponent c, String text); je vytvoˇren jednoduch´ y dialog zobrazuj´ıc´ı zadan´ y text. V titulku je zobrazen text “Message”, okno nedisponuje ˇz´ adnou ikonou.
Obr´ azek 10.36: ShowMessage dialog. Okno m˚ uˇze m´ıt vlastn´ı titulek, v z´ avislosti na informaci, kterou sdˇeluje; lze v nˇem zobrazovat nˇekolik typ˚ u ikon kter´e naznaˇcuj´ı charakter okna (informaˇcn´ı, v´ ystraˇzn´e, chybov´e...). Syntaxe vypad´ a takto JOptionPane.showMessageDialog(JComponent c, String text, String nadpis, int JOptionPane); Hodnoty konstant jsou uvedeny v n´ asleduj´ıc´ı tabulce.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Konstanta
Popis
PLAIN_MESSAGE
Okno neobsahuje ˇ z´ adnou ikonu, pouze prost´ y text.
WARNING_MESSAGE
V´ ystraˇ zn´ e okno
ERROR_MESSAGE
Chybov´ e okno.
INFORMATION_MESSAGE
Informaˇ cn´ı okno.
Tabulka 10.14: Pˇrehled konstant tˇr´ıdy JOptionPane. V´ ysledky vypadaj´ı takto.
Obr´ azek 10.37: Okno s prost´ym textem, v´ystraˇzn´e okno, chybov´e okno, informaˇcn´ı okno.
showOptionDialog. Tento mod´ aln´ı dialog m´ a ˇsirˇs´ı moˇznosti neˇz pouh´e zobrazen´ı zpr´ avy. Jeho vzhled i funkˇcnost mohou b´ yt v´ yraznˇeji modifikov´ any. Zobraz´ıme ho metodou JOptionPane.showMessageDialog(), kter´ a je opˇet pˇret´ıˇzena. Pop´ıˇseme ho pouze struˇcnˇe, ˇradu dalˇs´ıch informac´ı lze nal´ezt v dokumentaci. int s showOptionDialog(Component parent, Object text, String title, int optionType, int messageType,Icon icon, Object[] options, Object initialValue); Metoda obsahuje ˇradu parametr˚ u, jejich struˇcn´ y popis je uveden v n´ asleduj´ıc´ı tabulce. Parametr
Popis
Component parent
Jm´ eno nadˇrazen´ e komponenty.
Object text
Text zobrazen´ y v dialogov´ em oknˇ e.
String title
Nadpis dialogov´ eho okna.
int optionType
Typ tlaˇ c´ıtek, kter´ e budou v dialogu zobrazeny.
int messageType
Typ ikony, kter´ a je v dialogu zobrazena.
Icon icon
Ikona zobrazen´ a ve stavov´ em ˇr´ adku okna.
Object [] options
Popisy jednotliv´ ych tlaˇ c´ıtek dialogu.
Object initialValue
V´ ychoz´ı hodnota, kter´ a m˚ uˇ ze b´ yt nastavena (souˇ c´ ast´ı okna m˚ uˇ ze b´ yt i combo box)
Tabulka 10.15: Pˇrehled parametr˚ u ShowOption dialogu. Pr´ ace s ikonami je stejn´ a jako v pˇr´ıpadˇe message dialogu, nebudeme ji proto uv´ adˇet. Typy tlaˇc´ıtek zobrazen´ ych v dialogu jsou d´ any konstantou, kter´ a m˚ uˇze nab´ yvat n´ asleduj´ıc´ıch hodnot.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Konstanta
Popis
NO_OPTION
Tlaˇ c´ıtko No
OK_CANCEL_OPTION
Tlaˇ c´ıtka OK a Cancel
OK_OPTION
Tlaˇ c´ıtko OK
YES_NO_CANCEL_OPTION
Tlaˇ c´ıtka YES, NO, CANCEL
YES_NO_OPTION
Tlaˇ c´ıtka YES, NO
CANCEL_OPTION
Tlaˇ c´ıtko CANCEL
YES_OPTION
Tlaˇ c´ıtko YES
Tabulka 10.16: Typy tlaˇc´ıtek zobrazovan´ ych v ShowOption dialogu. Uk´ azka zdrojov´eho k´ odu: Object[] options = {"Ano","Ne","Neruˇ s mˇ e"}; int s=JOptionPane.showOptionDialog(this,M´ ate r´ adi programov´ an´ ı?", Ot´ azka",JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE, null, options, options[2]); V´ ysledek vypad´ a takto.
Obr´ azek 10.38: Tˇr´ıtlaˇc´ıtkov´ a varianta. Chceme -li vzhled okna upravit, pouˇzijeme jinou variantu pˇret´ıˇzen´e metody showOptionDialog(). Tlaˇc´ıtka nemus´ı m´ıt vlastn´ı popis, lze pouˇz´ıt defaultn´ı hodnoty. int s=JOptionPane.showConfirmDialog(this, "M´ ate r´ adi programov´ an´ ı?", "Ot´ azka",JOptionPane.YES_NO_OPTION); Kombinace ˇcesk´eho a anglick´eho jazyka nep˚ usob´ı dobˇre, mˇeli bychom se j´ı vyh´ ybat.
Obr´ azek 10.39: Dvoutlaˇc´ıtkov´ a ˇcesko-anglick´ a varianta. Uk´ azka tˇret´ı varianty pˇret´ıˇzen´e metody se dvˇema tlaˇc´ıtky: Object[] opt = {"Ano","Ne"}; int s=JOptionPane.showOptionDialog(this,"M´ ate r´ adi programov´ an´ ı?", "Ot´ azka",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null, opt, opt[0]);
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E V´ ysledek vypad´ a takto.
Obr´ azek 10.40: Upraven´ a dvoutlaˇc´ıtkov´ a varianta v ˇcesk´em jazyce. Detekce stisknut´ eho tlaˇ c´ıtka. Metoda showOptionDialog() vrac´ı k´ od stisknut´eho tlaˇc´ıtka. M˚ uˇzeme tak detekovat, kter´ ym tlaˇc´ıtkem uˇzivatel dialog zavˇrel. if (s==JOptionPane.YES_OPTION) { //stiskl uzivatel tlacitko YES? } Vytvoˇ ren´ı vlastn´ıho dialogu. Vlastn´ı dialog lze vytvoˇrit jako instanci tˇr´ıdy JDialog. Pr´ ace s n´ım je podobn´ a, jako v pˇr´ıpadˇe formul´ aˇr˚ u, nebudeme ji tedy uv´ adˇet. Na dialog m˚ uˇzeme pˇrid´ avat dalˇs´ı komponenty, pouˇz´ıvat layout managery, atd... Dialogu je moˇzno nastavit modalitu/nemodalitu a to za pouˇzit´ı metody setModal(boolean b). Zobrazen´ı dialogu je moˇzn´e prov´est metodou setVisible(boolean b). N´ asleduj´ıc´ı k´ od vytvoˇr´ı mod´ aln´ı dialog. JDialog jd=new JDialog(); jd.setTitle("Vlastn´ ı dialog"); jd.setModal(true); jd.setVisible(true) 10.1.8.10
JFileChooser
Tento mod´ aln´ı dialog slouˇz´ı pro v´ ybˇer souboru, je jedn´ım z nejˇcastˇeji pouˇz´ıvan´ ych dialog˚ u. K dipozici je nˇekolik konstruktor˚ u JFileChooser(); JFileChooser(String directory); Prvn´ı konstruktor vytvoˇr´ı dialog zobrazuj´ıc´ı pˇri otevˇren´ı bˇeˇzn´ y adres´ aˇr (current directory), druh´ y konstruktor dialog vytv´ aˇrej´ı dialog zobrazuj´ıc´ı zadan´ y adres´ aˇr. Reˇ zimy dialogu JFileChooser m˚ uˇze pracovat ve dvou reˇzimech. Prvn´ım je reˇzim, ve kter´em soubory m˚ uˇzeme otev´ırat, druh´ ym je reˇzim, ve kter´em soubory m˚ uˇzeme ukl´ adat. Fyzick´e otevˇren´ı ani uloˇzen´ı souboru nen´ı provedeno, pouze je vr´ acen odkaz na vybran´ y soubor. Reˇzimy jsou d´ any konstantami OPEN_DIALOG nebo SAVE_DIALOG, je moˇzno nastavit metodou setDialogType(DialogType d). fc.setDialogType(JFileCooser.OPEN_DIALOG) fc.setDialogType(JFileCooser.SAVE_DIALOG) Oba dialogy se liˇs´ı n´ azvem titulku a popisem tlaˇc´ıtka.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Vytvoˇ ren´ı dialogu. Pro zobrazen´ı open dialogu je pouˇz´ıv´ ana metoda int showOpenDialog(JComponent c), pro zobrazen´ı save dialogu je pouˇz´ıv´ ana metoda int showSaveDialog(JComponent c). Metody vracej´ı k´ od stisknut´eho tlaˇc´ıtka. M˚ uˇzeme tak detekovat, zda uˇzivatel provedl volbu nˇejak´eho souboru. Vytvoˇrme open dialog zobrazuj´ıc´ı pˇri startu obsah adres´ aˇre C:\\Eclipse. JFileChooser fc=new JFileChooser("C:\\eclipse"); int fc.showOpenDialog(this); V´ ysledek vypad´ a takto.
Obr´ azek 10.41: Uk´ azka dialog˚ u v reˇzimech open a save. Chceme -li dialogu nastavit titulek, pouˇzijeme metodu setDialogTitle(String text). fc.setDialogTitle("Otevˇ ren´ ı souboru"); V´ ybˇ er souboru. Detekce vybran´eho souboru je moˇzn´e prov´est po stisknut´ı tlaˇc´ıtka Open/Save za pouˇzit´ı testu n´ avratov´e hodnoty metod showOpenDialog() nebo showSaveDialog(). Pro z´ısk´ an´ı jm´ena vybran´eho souboru pouˇzijeme metodu getSelectedFile(File f). Detekci, zda bylo okno zavˇreno stiskem tlaˇc´ıtka Open/Save, provedeme za pouˇzit´ı konstant APPROVE_OPTION a CANCEL_OPTION. Konstanta
Popis
APPROVE_OPTION
Detekce, zda dialog uzavˇren Open/Save
CANCEL_OPTION
Detekce, zda dialog uzavˇren Cancel.
Tabulka 10.17: Detekce uzavˇren´ı dialogu. V´ ysledn´ y k´ od m˚ uˇze vypadat napˇr. takto if (fc.showOpenDialog(this)==fc.APPROVE_OPTION) { //nejaky kod System.out.println(fc.getSelectedFile().toString()); } Nastaven´ı masky. V oknech file chooseru nemus´ı b´ yt nutnˇe zobrazeny vˇsechny typy soubor˚ u. Typy zobrazen´ ych soubor˚ u mohou b´ yt omezeny za pouˇzit´ı pˇr´ıkazov´e masky. M˚ uˇzeme tak zobrazovat pouze soubory stejn´eho typu, s jak´ ymi pracuje naˇse aplikace. Pro definici filtr˚ u slouˇz´ı tˇr´ıda FileFilter.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E 10.1.8.11
JPanel
Panel pˇredstavuje nejjednoduˇsˇs´ı typ kontejnerov´e komponenty. Jeho jedin´ ym u ´kolem je organizovat komponenty, kter´e jsou v nˇem obsaˇzeny. Panely se pouˇz´ıvaj´ı pˇri n´ avrhu vzhledu okna. Za pouˇzit´ı vhodn´eho layout manageru um´ıst´ıme na formul´ aˇr panely, na tyto panely n´ aslednˇe dalˇs´ı komponenty. Pro JPanel lze pouˇz´ıt n´ asleduj´ıc´ı konstruktory: JPanel(); JPanel(LayoutManager); Prvn´ı konstruktor vytvoˇr´ı panel s v´ ychoz´ım layout managerem (FlowLayout), druh´ y konstruktor vytvoˇr´ı panel s rozloˇzen´ım komponent dle zadan´eho layout manageru. Vzhled panelu a jeho okraje (borders) je moˇzno nastavit prostˇrednictv´ım metody setBorder (Border b). V Javˇe existuje nˇekolik typ˚ u border˚ u, jejich pˇrehled je uveden v n´ asleduj´ıc´ı tabulce. Border
Varianty
BevelBorder
BevelBorder.LOWERED BevelBorder.RAISED
CompoundBorder
-
EmptyBorder
-
EtchedBorder
EtchedBorder.LOWERED EtchedBorder.RASISED
LineBorder
LineBorder.createBlackLineBorder() LineBorder.createGrayLineBorder()
SoftBevelBorder
SoftBevelBorder.LOWERED SoftBevelBorder.RAISED
TitledBorder
TitledBorder.DEFAULT_POSITION TitledBorder.LEFT TitledBorder.RIGHT TitledBorder.TOP TitledBorder.BOTTOM
Tabulka 10.18: JPanel a typy border˚ u. Popis jednotliv´ ych border˚ u nebudeme z d˚ uvodu rozs´ ahlosti prov´ adˇet, uvedeme pouze dvˇe doporuˇcen´ı. Pokud budeme cht´ıt pouˇz´ıt border bez ohraniˇcen´ı pouze jako podkladovou komponentu pro jin´e komponenty, pouˇzijeme EmptyBorder. Chceme -li pouˇz´ıt border ohraniˇcuj´ıc´ı komponenty na JPanelu, pouˇzijeme TitledBorder. Nastaven´ı borderu pro panel prov´ ad´ıme metodou setBorder(Border b). V n´ asleduj´ıc´ım pˇr´ıkladu vytvoˇr´ıme dva panely, obˇema nastav´ıme TitledBorder a kaˇzd´emu z nich titulek. Komponenty na formu budou vyuˇz´ıvat GridLayout. Pro vytvoˇren´ı panel˚ u pouˇzijeme implicitn´ı konstruktory. JPanel p1=new JPanel(); JPanel p2=new JPanel(); Vytvoˇr´ıme dvˇe instance tˇr´ıdy TitledBorder, v konstruktoru uvedeme titulky. TitledBorder b1=new TitledBorder("Prvn´ ı"); TitledBorder b2=new TitledBorder("Druh´ y"); Nastav´ıme polohu titulku na v´ ychoz´ı pozici, tj. vlevo nahoru.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E b1.setTitlePosition(TitledBorder.DEFAULT_POSITION); b2.setTitlePosition(TitledBorder.DEFAULT_POSITION); Obˇema panel˚ um nastav´ıme vytvoˇren´e bordery. p1.setBorder(b1); p2.setBorder(b2); V´ ysledn´ y k´ od vypad´ a takto. public Panely(int width, int height) { this.setSize(width, height); this.setTitle("Panely"); this.setLayout(new GridLayout(2,1)); JPanel p1=new JPanel(); JPanel p2=new JPanel(); TitledBorder b1=new TitledBorder("Prvn´ ı"); TitledBorder b2=new TitledBorder("Druh´ y"); b1.setTitlePosition(TitledBorder.DEFAULT_POSITION); b2.setTitlePosition(TitledBorder.DEFAULT_POSITION); p1.setBorder(b1); p2.setBorder(b2); this.getContentPane().add(p1); this.getContentPane().add(p2); } V´ ysledek vypad´ a takto.
Obr´ azek 10.42: Vzhled TitleBorder. Do kaˇzd´eho z panel˚ u m˚ uˇzeme n´ aslednˇe pˇridat dvˇe tlaˇc´ıtka. Obˇema panel˚ um nastav´ıme opˇet BorderLayout. p1.setLayout(new GridLayout(1,2)); p2.setLayout(new GridLayout(1,2)); Vytvoˇr´ıme dvˇe tlaˇc´ıtka a metodou add() je pˇrid´ ame na panely. Pˇri pr´ aci s panely jiˇz nen´ı potˇreba pracovat s grafick´ ym kontextem komponenty prostˇrednictv´ım metody getContentPane().
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.43: Vzhled TitleBorder se ˇctveˇric´ı tlaˇc´ıtek. V´ ysledn´ y k´ od vypad´ a takto. JButton but1=new JButton but2=new JButton but3=new JButton but4=new p1.add(but1); p1.add(but2); p2.add(but3); p2.add(but4)
10.1.9
JButton("Prvni"); JButton("Druhe"); JButton("Treti"); JButton("Ctvrte");
Grafika
V t´eto kapitole se sezn´ am´ıme se z´ aklady grafiky v Javˇe nad rozhran´ım Swing. Nauˇc´ıme se kreslit na plochu komponent, pouˇz´ıvat barvy ˇci naˇc´ıst rastrov´ a data. Budeme pracovat s tˇr´ıdou Graphics, kter´ a umoˇzn ˇ uje z´ akladn´ı grafick´e operace. Pro pokroˇcilejˇs´ı kresbu lze pouˇz´ıt tˇr´ıdu Graphics2D, kter´ a je tak´e souˇc´ ast´ı Javy, jej´ı popis zde jiˇz neuv´ ad´ıme. V Javˇe m˚ uˇzeme kreslit jak 2D, tak i 3D objekty. Existuje velk´e mnoˇzstv´ı extern´ıch tˇr´ıd obsahuj´ıc´ıch n´astroje prov´ adˇej´ıc´ı ˇradu pokroˇcil´ ych grafick´ ych operac´ı jako rendering, animaci, pr´ aci s multim´edii. Java dok´aˇze vyuˇz´ıvat knihovny OpenGL. Rychlost grafiky v Javˇ e. V praxi se ˇcasto setk´ av´ ame s argumentem, ˇze grafika v Javˇe je pomal´ a. Uved’me toto tvrzen´ı na spr´ avnou m´ıru. Tento nedostatek se projevoval zejm´ena u prvn´ıch verz´ı jazyka Java, rychlost interpretovan´eho k´ odu byla aˇz 30 niˇzˇs´ı neˇz u kompilovan´eho C++. V takov´em pˇr´ıpadˇe bylo moˇzno oznaˇcit grafiku v Javˇe za pomˇernˇe pomalou. V souˇcasn´e dobˇe je Java asi 2x pomalejˇs´ı neˇz C++ (pˇribliˇzn´ yu ´daj), grafiku v Javˇe m˚ uˇzeme povaˇzovat za pomˇernˇe rychlou. Kdy dojde k vykreslen´ı obrazu? Pˇri kreslen´ı v Javˇe za pouˇzit´ı tˇr´ıdy Graphics nem˚ uˇzeme pˇresnˇe urˇcit okamˇzik, kdy dojde k vykreslen´ı obrazu. Kresba je provedena v okamˇziku, kdy to grafick´e rozhran´ı povaˇzovat za nezbytn´e. Pˇrekreslen´ı obrazu vˇsak m˚ uˇzeme vyvolat ”umˇele” prostˇrednictv´ım metody repaint(). Tento zp˚ usob je ponˇekud nezvykl´ y, vede vˇsak uˇzivatele k tomu, ˇze nen´ı moˇzn´e na plochu okna kreslit bez syst´emu v okamˇziku, kdy se mu zrovna zachce. Je zp˚ usoben t´ım, ˇze vykreslov´ an´ı nesm´ı b´ yt pˇreruˇseno ˇz´adnou jinou ˇcinnost´ı, proto JVM vyˇck´ av´ a na vhodn´ y okamˇzik. Vykreslov´ an´ı prob´ıh´ a hierarchicky od komponent s vyˇsˇs´ı hierarchi´ı sestupnˇe ke komponent´ am s niˇzˇs´ı hierarchi´ı.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Double buffering. Java pro zv´ yˇsen´ı kvality podporuje vykreslov´ an´ı techniku double bufferingu. Vykreslov´ an´ı v takov´em pˇr´ıpadˇe neprob´ıh´ a po pˇr´ımo na komponentˇe, ale ve specializovan´em bufferu v pamˇeti. Po vykreslen´ı do bufferu je obr´ azek “pˇrenesen” na komponentu jako celek. V´ ysledkem je kvalitnˇejˇs´ı obraz neˇz pˇri klasick´em pˇr´ıstupu. Kresl´ıc´ı plocha m´ a v Javˇe tvar obd´eln´ıka. Pro zv´ yˇsen´ı rychlosti vykreslov´ an´ı se v Javˇe ˇcasto pouˇz´ıv´a trik, kdy komponenty oznaˇc´ıme za pr˚ uhledn´e. Grafick´e rozhran´ı pak nemus´ı ztr´ acet ˇcas s jejich vykreslov´an´ım. Vykreslov´ an´ı prob´ıh´ a na pl´ atno komponenty, kter´e se naz´ yv´ a Canvas. Metody pro kreslen´ı ve Swingu. Jak jsme uvedli v u ´vodu, pˇri pˇrekreslov´ an´ı je pouˇz´ıv´ an hierarchick´ y model. Ten ud´ av´ a poˇrad´ı pˇrekreslov´ an´ı jednotliv´ ych grafick´ ych kompoment na formul´ aˇri. Nejprve je vykresleno pozad´ı formul´ aˇre, n´ aslednˇe vykreslen´ı grafiky, pot´e okraj komponenty a jako posledn´ı komponenty s niˇzˇs´ı hierarchi´ı um´ıstˇen´e na t´eto komponentˇe. Postup je realizov´ an trojic´ı metod.
Obr´ azek 10.44: Postup pˇrekreslen´ı komponenty. 1. Metoda paintComponent() je nejd˚ uleˇzitˇejˇs´ı metodou, kter´ a se pouˇz´ıv´ a pˇri prekreslov´ an´ı komponent. Nejprve prov´ ad´ı pˇrekreslen´ı pozad´ı, pot´e prov´ ad´ı vykreslen´ı grafiky. Tato metoda m˚ uˇze, a ˇcasto b´ yv´a, uˇzivatelem pˇredefinov´ ana, umoˇzn ˇuje mu ovlivnit zp˚ usob vykreslov´ an´ı vlastn´ı grafiky. 2. N´ aslednˇe metoda paintBorder() provede vykreslen´ı okraje komponenty. Tato metoda by nemˇela b´ yt uˇzivatelem pˇredefinov´ av´ ana. 3. Metoda paintChildren() provede vykreslen´ı komponent na hierarchicky niˇzˇs´ı u ´rovni. Ani tato metoda by nemˇela b´ yt uˇzivatelem pˇredefinov´ ana. Princip pˇ rekreslen´ı plochy. Pˇrekreslen´ı plochy komponenty je provedeno po vyvol´ an´ı metody repaint(). Tato metoda zavol´ a nejprve metodu update(), kter´ a pˇres komponentu nakresl´ı vyplnˇen´ y obd´eln´ık v barvˇe pozad´ı a tak vlastnˇe kresbu vymaˇze. N´ aslednˇe je zavol´ ana metoda paintComponent(), kter´ a provede vykreslen´ı. Vyvol´ an´ım metody repaint() dojde vˇzdy k smaz´ an´ı p˚ uvodn´ı kresby. Metoda repaint je pˇret´ıˇzen´a, uved’me nˇekter´e prototypy: repaint(); repaint(int time); repaint(int time, int x, int y, int width, int heigh); Prvn´ı metoda provede pˇrekreslen´ı v okamˇziku, kdy to syst´em uzn´ a za vhodn´e, druh´ a v zadan´em ˇcase v milisekund´ ach, tˇret´ı pˇrekresl´ı pouze oblast zadanou v´ yˇrezem v zadan´em ˇcase v milisekund´ ach. 10.1.9.1
Z´ akladn´ı entity a jejich kresba
V t´eto kapitole se sezn´ am´ıme se z´ akladn´ımi grafick´ ymi entitami a metodami jejich vykreslov´ an´ı v GUI Javy. Kaˇzd´ y sloˇzitˇejˇs´ı u ´tvar lze z tˇechto entit sloˇzit, pˇredstavuj´ı tedy z´ akladn´ı stavebn´ı jednotku v´ ykresu. Upozornˇeme, ˇze ve tˇr´ıdˇe Graphics nem˚ uˇzeme nastavit linii ˇs´ıˇrku a typ, z grafick´ ych atribut˚ u j´ı m˚ uˇzeme nastavit pouze barvu. Struˇcnˇe popiˇsme nˇekter´e grafick´e entity:
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Linie. Pro kresbu linie je pouˇz´ıv´ ana metoda drawLine(int x1, int y1, int x2, int y2). Vykresl´ı linii jdou z poˇc´ ateˇcn´ıho bodu P1 = [x1 , y1 ] do koncov´eho bodu P2 = [x2 , y2 ]. Eliptick´ a v´ yseˇ c. Kresbu eliptick´e v´ yseˇce lze prov´est metodou drawArc(int x, int y, int sirka, int vyska, int start_uhel, int konc_uhel). Souˇradnice x, y pˇredstavuj´ı lev´ y horn´ı roh obd´eln´ıka zadan´e ˇs´ıˇrky a d´elky, do kter´eho je v´ yseˇc veps´ ana, jsou d´ any poˇc´ ateˇcn´ı a koncov´ yu ´hel ovlivˇ nuj´ıc´ı ”d´elku” oblouku. Elipsa. Metoda drawOval(int x, int y, int sirka, int vyska) slouˇz´ı k vykreslen´ı elipsy vepsan´e do obd´eln´ıku zadan´e ˇs´ıˇrky a d´elky, jsou d´ any souˇradnice lev´eho horn´ıho rohu obd´eln´ıka. Polygon. Polygon pˇredstavuje uzavˇrenou oblast definovanou lomov´ ymi body spojen´ ymi u ´seˇckami. Lze ho nakreslit metodou drawPolygon(), kter´ a je pˇret´ıˇzen´ a. Existuj´ı dvˇe varianty: drawPolygon(int [x], int [y], int pocet_vrcholu) a drawPolygon(Polygon p). V prvn´ı je polygon definov´ an polem x-ov´ ych a yov´ ych souˇradnic, druh´ y objektem typu polygon. Polyline. Polyline pˇredstavuje lomenou ˇc´ aru, lze ho nakreslit metodou drawPolyline( int [x], int [y], int pocet_vrcholu). V´ yznam parametr˚ u je stejn´ y jako u polygonu. Obd´ eln´ık. Pro kresbu obd´eln´ıku slouˇz´ı metoda drawRect(int x, int y, int sirka, int vyska). V´ yznam parametr˚ u je stejn´ y jako u elipsy. 3D obd´ eln´ık. Metoda draw3DRect(int x, int y, int sirka, int vyska, boolean stav) vytvoˇr´ı plastick´ y obd´eln´ık pˇripom´ınaj´ıc´ı tlaˇc´ıtko. Tlaˇc´ıtko m˚ uˇze b´ yt zam´ aˇckl´e nebo nikoliv, rozhoduje o tom booleovsk´a promˇenn´ a stav. Text. Pro um´ıstˇen´ı textu na specifick´e souˇradnice je pouˇz´ıv´ ana metoda drawString( String text, int x, int y). Vyplˇ nov´ an´ı entit barvou. Dalˇs´ı skupinu n´ astroj˚ u tvoˇr´ı metody pro vyplˇ nov´ an´ı nˇekter´ ych v´ yˇse uveden´ ych ´ entit barvou. Utvary jsou standardnˇe vyplˇ nov´ any stejnou barvou, jakou byly nakresleny. Pˇripomeˇ nme metody setColor( Color c) a getColor() pro nastaven´ı a z´ısk´ an´ı barvy. Pokud chceme vyplnit u ´tvar jinou barvou, neˇz je nakreslen jeho obrys, postupujeme n´ asledovnˇe. nastav´ıme barvu pro v´ yplˇ n a vypln´ıme u ´tvar, zmˇen´ıme barvu vykresl´ıme obrys u ´tvaru. Parametry metod jsou stejn´e jako v pˇr´ıpadˇe metod pro kresbu nevyplnˇen´ ych entit. Vyplnˇ en´ y 3D obd´ eln´ık. Metoda fill3DRect(int x, int y, int sirka, int vyska, boolean stav) nakresl´ı vyplnˇen´ y plastick´ y obd´eln´ık. Vyplnˇ en´ a eliptick´ a v´ yseˇ c. Metoda fillArc(int x, int y, int sirka, int vyska, int start_uhel, int konc_uhel) slouˇz´ı k nakreslen´ı vyplnˇen´e eliptick´e oblasti. Vyplnˇ en´ a elipsa. Metoda fillOval(int x, int y, int sirka, int vyska) umoˇzn ˇuje nakreslen´ı vyplnˇen´e elipsy.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Vyplnˇ en´ y polygon. Pro kresbu vyplnˇen´eho polygonu jsou pouˇz´ıv´ any metody fillPolygon(int [x], int [y], int pocet_vrcholu) nebo fillPolygon(Polygon p). Vyplnˇ en´ y obd´ eln´ık. Metoda drawRect(int x, int y, int sirka, int vyska), slouˇz´ı pro kresbu vyplnˇen´eho obd´eln´ıku. 10.1.9.2
Pˇ r´ıklady
Informace, kter´e jsme z´ıskali se nyn´ı pokus´ıme aplikovat ve tˇrech pˇr´ıkladech. Pˇ r´ıklad 1. Prvn´ı z pˇr´ıklad˚ u bude generovat soustˇredn´e kruˇznice se stˇredem ve stˇredu okna s krokem 10 pixel˚ u. Vykreslov´ an´ı bude provedeno v tˇr´ıdˇe, kter´ a je potomkem tˇr´ıdy JComponent. Formul´ aˇr bude vytvoˇren ve tˇr´ıdˇe, kter´ a bude potomkem tˇr´ıdy JFrame. Vykreslov´ an´ı nebudeme prov´ adˇet pˇr´ımo na pl´ atno formul´aˇre, ale na komponentu JPanel pˇridanou na formul´ aˇr. public class Main3 extends JFrame{ public Main3(int width, int height) { this.setSize(width,height); this.setTitle("Kruznice"); JPanel p=new JPanel(); p.add(new Draw()); this.getContentPane().add(p); p.setLayout(new BorderLayout()); p.add(new Kruznice(width,height)); this.setVisible(true); } public static void main (String [] args) { new Main3(300,200); } Vˇsimnemˇe si, ˇze na panel pˇrid´ ame metodou add() novou instanci tˇr´ıdy Kruznice, kter´ a bude zajiˇst’ovat vykreslen´ı. Tento postup lze zobecnit, instanci tˇr´ıdy prov´ adˇej´ıc´ı kresbu tedy pˇrid´ av´ ame na komponentu, na kterou se bude kreslen´ı prov´ adˇet. Implementace tˇr´ıdy Kruznice vypad´ a takto. public class Kruznice extends JComponent{ private int sirka, vyska; public Kruznice(int sirka, int vyska) { this.sirka=sirka; this.vyska=vyska; } public void paintComponent(Graphics g) { for (int i=0;(i
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E V´ ysledek vypad´ a takto.
Obr´ azek 10.45: Vykreslen´ı soustˇredn´ych kruˇznic. Pˇ r´ıklad 2. Pˇr´ıklad ilustruje pr´ aci s rozhran´ımi MouseListener, a MouseMotionListener. Budeme vytv´aˇret v´ ybˇerovou mnoˇzinu ve tvaru obd´eln´ıku (tj. ohradu), jej´ıˇz rozmˇery se budou mˇenit na z´ akladˇe polohy myˇsi. Zamysleme se, pˇri kter´ ych ud´ alostech myˇsi budeme prov´ adˇet vykreslov´ an´ı ohrady. Po stisknut´ı tlaˇc´ıtka na myˇsi zjist´ıme aktu´ aln´ı pozici kurzoru, oˇsetˇrujeme handler mousePressed(). Tlaˇc´ıtko myˇsi drˇz´ıme st´ ale stisknut´e, odeˇc´ıt´ ame polohu aktu´ aln´ı pozice kurzoru, tj. oˇsetˇrujeme metodu mouseDragged(), pˇri kter´e prov´ ad´ıme vykreslov´ an´ı obd´eln´ıka. Po uvolnˇen´ı tlaˇc´ıtka na myˇsi (metoda mouseReleased()) nebudeme prov´ adˇet ˇz´ adnou akci. Ohrada na ploˇse z˚ ustane aˇz do dalˇs´ıho zad´ av´ an´ı. Souˇradnice lev´eho horn´ıho a prav´eho doln´ıho rohu ohrady budeme ukl´adat do promˇenn´ ych typu int. Ve tˇr´ıdˇe main deklarujeme potˇrebn´e promˇenn´e, vytvoˇr´ıme JPanel, kter´ y um´ıst´ıme na formul´ aˇr. Kreslen´ı bude prob´ıhat ve tˇr´ıdˇe Draw, jej´ıˇz instanci tak´e vytvoˇr´ıme. public class Main extends JFrame{ private int x1, y1, x2, y2; private Draw d; public Main(int width, int height) { this.setSize(width, height); this.setTitle("Ohrada"); this.setLayout(new GridLayout(1,1)); JPanel p=new JPanel(); p.setBackground(Color.WHITE); p.setLayout(new BorderLayout()); d=new Draw(); p.add(d); this.getContentPane().add(p); this.setVisible(true); ... } Pro JPanel zaregistrujeme posluchaˇce, pouˇzijeme dvˇe rozhran´ı: MouseListener a MouseMotionListener. Vˇsechny jejich metody mus´ı b´ yt pˇredefinov´ any. N´ as budou zaj´ımat metody mousePressed() a mouseDragged(). V prvn´ım handleru inicializujeme souˇradnice lev´eho horn´ıho a prav´eho doln´ıho rohu tak, aby byly totoˇzn´e, ve druh´em handleru mˇen´ıme souˇradnice pouze prav´eho doln´ıho rohu. Pro z´ısk´ an´ı polohy kurzoru pouˇzijeme metody getX() a getY(), kter´e vol´ ame pro parametry obou handler˚ u. p.addMouseListener(new MouseListener()
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E { public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mousePressed(MouseEvent e) { x1=e.getX(); y1=e.getY(); x2=e.getX(); y2=e.getY(); d.setRectangle(x1,y1, x2,y2); } public void mouseReleased(MouseEvent e){} public void mouseExited(MouseEvent e){} }); p.addMouseMotionListener(new MouseMotionListener() { public void mouseDragged(MouseEvent e) { x2=e.getX(); y2=e.getY(); d.setRectangle(x1,y1, x2,y2); repaint(); } public void mouseMoved(MouseEvent e) {} }); } Vykreslen´ı budeme prov´ adˇet v metodˇe paintComponent() tˇr´ıdy Draw. Hodnoty aktu´ aln´ıch souˇradnice obou roh˚ u jsou pˇred´ av´ any metodou setRectangle(). public class Draw extends JComponent{ private int x1,y1, x2, y2; public Draw() { } public void paintComponent(Graphics g) { g.setColor(Color.RED); g.drawRect(x1,y1,x2-x1, y2-y1); } public void setRectangle(int x1, int y1,int x2, int y2) { this.x1=x1; this.y1=y1; this.x2=x2; this.y2=y2; } }
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E V´ ysledek vypad´ a takto.
Obr´ azek 10.46: Vykreslen´ı v´ybˇerov´e mnoˇziny. Pˇ r´ıklad 3. V n´ asleduj´ıc´ım pˇr´ıkladu se budeme pokouˇset vytvoˇrit program, kter´ y bude generovat u ´seˇcky s n´ ahodn´ ymi hodnotami souˇradnic koncov´ ych bod˚ u a n´ ahodnou hodnotou barvy. Souˇradnice jednotliv´ ych poˇc´ ateˇcn´ıch a koncov´ ych bod˚ u budeme ukl´ adat do dynamick´e datov´e struktury ArrayList. Poˇcet u ´seˇcek je zn´ am pˇredem, v´ ypoˇcet tedy probˇehne v cyklu for. Pˇri n´ avrhu struktury tˇr´ıd pouˇzijeme princip kompozice a to na z´ akladˇe u ´ vahy ”M´ au ´seˇcka nˇejak´e body?” Nejprve vytvoˇr´ıme tˇr´ıdu Bod, bude obsahovat dvˇe datov´e poloˇzky pˇredstavuj´ıc´ı souˇradnice x, y bodu. public class Bod { private int x,y; public Bod(int x, int y) { this.x=x; this.y=y; } } ´ cku budou tvoˇrit poˇc´ Useˇ ateˇcn´ı a koncov´ y bod, bude m´ıt uloˇzeny informace o barvˇe. Nov´e instance tˇr´ıdy Usecka budou vytv´ aˇreny za pouˇzit´ı explicitn´ıho konstruktoru, kaˇzd´e u ´seˇcka si nese informace o sv´ ych krajn´ıch bodech a barvˇe. Aby bylo moˇzno u ´ seˇcky moˇzno v cyklu vykreslit, ve tˇr´ıdˇe jsou implementov´ any metody (tj. gettery) vracej´ıc´ı informace o poˇc´ ateˇcn´ım, koncov´em bodˇe a barvˇe u ´seˇcky. public class Usecka { private Bod start, end; private Color col; public Usecka(int x1, int y1, int x2, int y2, Color col) { this.start=new Bod (x1, y1); this.end=new Bod (x2, y2); this.col=col; } public Bod getStart(){return this.start;} public Bod getEnd(){return this.end;} public Color getColor(){return this.col;} }
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Vlastn´ı generov´ an´ı u ´seˇcek prov´ ad´ı ve sv´em konstruktoru tˇr´ıda Generovani. Jako form´ aln´ı parametry jsou explicitn´ımu konstruktoru pˇred´ av´ any n´ asleduj´ıc´ı u ´daje: poˇcet u ´seˇcek, ˇs´ıˇrka a v´ yˇska JPanelu.Vygenerovan´e u ´seˇcky jsou ukl´ ad´ any do ArrayListu typu Usecky. Pro generov´ an´ı n´ ahodn´ ych ˇc´ısel pouˇzijeme statickou metodu random(), kter´ a se nach´ az´ı ve tˇr´ıdˇe Math. Ve tˇr´ıdˇe jsou d´ ale implementov´ any metody vracej´ıc´ıc´ı poˇcet vygenerovan´ ych u ´seˇcek a jednu u ´seˇcku. public class Generovani { private ArrayList <Usecka> u; public Generovani(int kolik, int width, int height) { u=new ArrayList <Usecka>(); for (int i=0; i
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E public class Main extends JFrame{ public Main(int width, int height) { this.setSize(width, height); this.setTitle("Usecky"); this.setLayout(new GridLayout(1,1)); Generovani g=new Generovani(30,width, height); JPanel p=new JPanel(); p.setBackground(Color.WHITE); p.setLayout(new BorderLayout()); p.add(new Draw(g)); this.getContentPane().add(p); p.add(new Draw(g)); this.setVisible(true); } public static void main(String[] args) { new Main(400,200); } } V´ ysledek vypad´ a takto.
Obr´ azek 10.47: Vykreslen´ı lini´ı s n´ ahodn´ymi souˇradnicemi i barvami. Pˇr´ıklad by d´ ale bylo moˇzno vylepˇsit pˇrid´ an´ım tlaˇc´ıtka generuj´ıc´ıho po kaˇzd´em stisku novou posloupnost u ´seˇcek. Na formul´ aˇr bychom pˇridali tlaˇc´ıtko. Pˇri umist’ov´ an´ı na formul´ aˇr pouˇzijeme BorderLayout, panel bude BorderLayout.CENTER, tlaˇc´ıtko BorderLayout.SOUTH. JButton b =new JButton("Generuj"); this.add(b, BorderLayout.SOUTH); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Generuj(e); } }); Metoda Generuj() vypad´ a takto: public void Generuj(ActionEvent e) { g=new Generovani(30,width, height); p=new JPanel();
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E p.setBackground(Color.WHITE); p.setLayout(new BorderLayout()); p.add(new Draw(g)); this.getContentPane().add(p,BorderLayout.CENTER); p.add(new Draw(g)); this.setVisible(true); } A v´ ysledek.
Obr´ azek 10.48: Pˇredchoz´ı pˇr´ıklad doplnˇen´y tlaˇc´ıtkem. 10.1.9.3
Pr´ ace s obr´ azky
V programu ˇcasto pracujeme s rastry. Java nativnˇe pracuje s form´ aty JPG, PNG a GIF. Rastry mohou b´ yt pˇripojov´ any jak z lok´ aln´ıho zdroje, tak ze vzd´ alen´eho poˇc´ıtaˇce prostˇrednictv´ım URL. Metody pro pr´aci s rastry nalezneme ve tˇr´ıd´ ach ImageIO, BufferedImage, ImageIcon. Tato problematika je pomˇernˇe rozs´ahl´a, Java disponuje ˇradou n´ astroj˚ u pro pr´ aci s rastry, omez´ıme se jen na velmi struˇcn´ y popis z´ akladn´ıch moˇznost´ı, pˇredevˇs´ım s postupem pro naˇcten´ı a uloˇzen´ı rastru. Pr´ ace s rastrem pˇredstavuje zpravidla dva kroky: prvn´ı tvoˇr´ı jeho naˇcten´ı, druh´ y jeho zobrazen´ı. Naˇ cten´ı rastru. Naˇcten´ı rastru lze prov´est nˇekolika zp˚ usoby. Uk´ aˇzeme dvˇe varianty, prvn´ı s vyuˇzit´ım tˇr´ıdy BufferedImage, druhou s vyuˇzit´ım tˇr´ıdy ImageIcon(). Naˇ cten´ı rastru z lok´ aln´ıho zdroje. Naˇcten´ı nejprve provedeme z lok´ alnˇe um´ıstˇen´eho souboru. Nejprve vytvoˇr´ıme instanci tˇr´ıdy File a inicializujeme ji cestou k souboru. Pˇripomeˇ nme, ˇze pˇri z´ apisu cesty mus´ıme pouˇz´ıvat dvojit´ a lom´ıtka, pˇri pouˇzit´ı jednoho lom´ıtka by se jednalo o ESCAPE sekvenci. File f=new File("C:\\zajic.png"); Vytvoˇr´ıme odkaz na instanci tˇr´ıdy BufferedImage BufferedImage im; Rastr naˇcteme statickou metodou tˇr´ıdy ImageIO.read(File f) a inicializujeme s n´ım odkaz im. im=ImageIO.read(f); Druhou moˇznost pˇredstavuje vyuˇzit´ı tˇr´ıdy ImageIcon. Vytvoˇr´ıme novou instanci tˇr´ıdy ImageIcon, v konstruktoru ji inicializujeme souborem s rastrem, konstruktor oˇcek´ av´ a na vstupu objekt typu String. Metodou toString() z´ısk´ ame n´ azev souboru.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E ImageIcon i=new ImageIcon(f.toString()); V dalˇs´ım kroku vytvoˇr´ıme odkaz na instanci tˇr´ıdy Image a inicializujeme ji prostˇrednictv´ım metody getImage() naˇcteme rastr. Image im=i.getImage(); Naˇ cten´ı rastru ze vzd´ alen´ eho zdroje. Pˇri naˇc´ıt´ an´ı rastru ze vzd´ alen´eho zdroje vytvoˇr´ıme novou instanci tˇr´ıdy URL, kterou inicializujeme odkazem na rastr. url=new URL("http://www.natur.cuni.cz/gis/tomas/1.jpg"); Dalˇs´ı postup je stejn´ y jako v pˇredchoz´ım pˇr´ıpadˇe im=ImageIO.read(url); Zobrazen´ı rastru. Pot´e, co je rastr naˇcten, je nutn´e ho zobrazit. Zpravidla se pouˇz´ıv´ a komponenta JPanel. Zobrazov´ an´ı rastru prob´ıh´ a v pˇredefinovan´e metodˇe paintComponent() za pouˇzit´ı metody drawImage(). Metoda je pˇret´ıˇzena, je k dispozici celkem 6 prototyp˚ u t´eto metody. Nejjednoduˇsˇs´ı varianta vypad´ a takto: boolean drawImage(Image img,int x,int y, ImageObserver observer) Metoda neupravuje velikost rastru, rastr se na komponentu nemus´ı vej´ıt cel´ y, v takov´em pˇr´ıpadˇe je zobrazena pouze lev´ a horn´ı ˇc´ ast rastru. Pokud bychom chtˇeli rastr zobrazit cel´ y, m˚ uˇzeme bud’ formul´ aˇr zvˇetˇsit, nebo um´ıstit JPanel na JScrollPane. Promˇenn´ a img pˇredstavuje odkaz na naˇcten´ y rastr, x, y souˇradnice lev´eho horn´ıho rohu rastru na komponentˇe, observer objekt, kter´ y je uvˇedomˇen, je -li rastr naˇcten. V naˇsem pˇr´ıpadˇe bude k´ od pro vykreslen´ı vypadat takto: public void paintComponent(Graphics g) { g.drawImage(im,0,0,this); } Druh´ y prototyp, kter´ y uvedeme, obsahuje parametry width/height, kter´e umoˇzn´ı stanovit novou velikost rastru. Rastr tedy m˚ uˇzeme dodateˇcnˇe zvˇetˇsit ˇci zmenˇsit. boolean drawImage(Image img, int x, int y, int sirka, int vyska, ImageObserver observer). Uloˇ zen´ı rastru. Rastr m˚ uˇzeme uloˇzit za pouˇzit´ı statick´e metody ImageIO.write(). Jej´ı prototyp vypad´a takto: write(RenderedImage im, String format, File soubor).
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Pr´ ace s pixely S jednotliv´ ymi pixely rastru lze manipulovat prostˇrednictv´ım metody setRGB(int x, int y, int color). Metoda umoˇzn ˇ uje nastavit pixelu zvolenou barvu, barva je vyj´ adˇrena prostˇrednictv´ım hodnoty int. Rastr se chov´ a jako matice, x pˇredstavuje ˇr´ adkov´ y index, y sloupcov´ y index. Hodnotu barvy ve zvolen´em pixelu lze z´ıskat metodou int getRGB(int x, int y), metoda vrac´ı ˇc´ıslo typu int. Chceme -li z´ıskat hodnoty jednotliv´ ych barevn´ ych sloˇzek, pouˇzijeme n´ asleduj´ıc´ı k´ od: c=getRGB(x,y); int red = (c & 0x00ff0000) > > 16; int green = (c & 0x0000ff00) > > 8; int blue = c & 0x000000ff; Velikost rastru lze zjistit metodami getWidht() a getHeight(). Pouˇz´ıvaj´ı se, pokud chceme v cyklu proch´azet rastrem po pixelech. V n´ asleduj´ıc´ım pˇr´ıkladu otevˇreme rastr nach´ azej´ıc´ı se ve vzd´ alen´em zdroji. Rastr zobraz´ıme, vˇsem pixel˚ um nastav´ıme hodnotu barevn´ ych sloˇzek n´ asledovnˇe Rnov = R/3, Gnov = G, Bnov = B/3. Naˇcten´ı rastru provedeme v metodˇe loadImage(). public void loadPicture() { try { url=new URL("http://www.natur.cuni.cz/gis/tomas/1.jpg"); im=ImageIO.read(url); } catch (Exception e) { e.printStackTrace(); } } Pro z´ısk´ an´ı hodnot barevn´ ych sloˇzek pouˇzijeme metodu getRGB(). Na z´ akladˇe poˇzadavku zad´ an´ı uprav´ıme hodnoty barevn´ ych sloˇzek R a B, vytvoˇr´ıme novou instanci tˇr´ıdy Color a pomoc´ı getRGB() pˇrevedeme jej´ı hodnotu na ˇc´ıslo typu int, tuto hodnotu nastav´ıme pro pixel metodou setRGB(). public void editPicture() { for (int i=0;i > 16; int green = (c & 0x0000ff00) > > 8; int blue = c & 0x000000ff; red=red/3; blue=blue/3; Color ce=new Color(red,green,blue); im.setRGB(i,j,ce.getRGB()); } } }
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E Upraven´ y rastr n´ aslednˇe uloˇz´ıme public void savePicture() { File soubor=new File("C::\\Temp\\Pokus.jpg"); try { ImageIO.write(im, "jpg", soubor); } catch (Exception e) { e.printStackTrace(); } } Pro zobrazen´ı pouˇz´ıv´ ame metodu drawImage(), velikost rastru nastav´ıme stejnou jako velikost JPanelu, na kter´e vykreslen´ı rastru prov´ ad´ıme. Pro nastaven´ı velikosti pouˇzijeme explicitn´ı konstruktor. public class Obrazek extends JComponent{ private int width, height; private URL url; private BufferedImage im; public Obrazek(int width, int heigth) { this.width=width; this.height=heigth; } public void loadPicture() { try { url=new URL("http://www.natur.cuni.cz/gis/tomas/1.jpg"); im=ImageIO.read(url); } catch (Exception e) { e.printStackTrace(); } } public void editPicture() { for (int i=0;i > 16; int green = (c & 0x0000ff00) > > 8; int blue = c & 0x000000ff;
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E red=red/3; blue=blue/3; Color ce=new Color(red,green,blue); im.setRGB(i,j,ce.getRGB()); } } } public void savePicture() { File soubor=new File("C::\\Temp\\Pokus.jpg"); try { ImageIO.write(im, "jpg", soubor); } catch (Exception e) { e.printStackTrace(); } } public void paintComponent(Graphics g) { g.drawImage(im,0,0, width,height, this); } } Nyn´ı vytvoˇr´ıme formul´ aˇr s grafick´ ym n´ avrhem, rastr zobraz´ıme v JPanelu. public class MainObrazek extends JFrame { public MainObrazek(int width, int height) { this.setSize(width, height); this.setTitle("Obrazek"); JPanel p=new JPanel(); p.setLayout(new BorderLayout()); Obrazek o=new Obrazek(width, height); o.loadPicture(); o.editPicture(); p.add(o); this.getContentPane().add(p); this.setVisible(true); } public static void main(String [] arg) { new MainObrazek(400,400); } } Uk´ azka p˚ uvodn´ıho a upraven´eho rastru.
´ UZIVATELSK ˇ ´ ROZHRAN´I KAPITOLA 10. JAVA, GRAFICKE E
Obr´ azek 10.49: Vlevo p˚ uvodn´ı, vpravo upraven´y rastr.
Kapitola 11
Aplety Aplet (v anglick´em jazyce applet) pˇredstavuje aplikaci menˇs´ıho rozsahu um´ıstˇenou do WWW strany, kter´a bˇeˇz´ı v oknˇe prohl´ıˇzeˇce. Aplet je spouˇstˇen po naˇcten´ı WWW strany, nem˚ uˇze tedy bˇeˇzet samostatnˇe bez prohl´ıˇzeˇce. Dˇr´ıve aplety pˇredstavovaly jedno z typick´ ych vyuˇzit´ı Javy, v souˇcasn´e dobˇe se Java pouˇz´ıv´a na ”seri´oznˇejˇs´ı” typy aplikac´ı. Aplety jsou proto pouˇz´ıv´any sp´ıˇse pro oˇziven´ı WWW str´anek ˇci uk´azku jednoduch´ ych algoritm˚ u. Aplety, na rozd´ıl od bˇeˇzn´ ych aplikac´ı, maj´ı nˇekter´a omezen´ı bezpeˇcnostn´ıho charakteru: • aplet nem˚ uˇze spouˇstˇet programy na domovsk´em serveru. • aplet nem˚ uˇze zapisovat do soubor˚ u v poˇc´ıtaˇci, na kter´em je spuˇstˇen. • aplet nem˚ uˇze navazovat spojen´ı jinam neˇz na domovsk´ y server. Aplety mohou b´ yt digit´ alnˇe podeps´ any, v takov´em pˇr´ıpadˇe nˇekter´a z bezpeˇcnostn´ıch omezen´ı neplat´ı. Problematikou digit´alnˇe podepsan´ ych aplet˚ u se tento materi´al nezab´ yv´a. Pokud budeme aplet pˇrekl´adat, je nutn´e vz´ıt v u ´ vahu, ˇze uˇzivatel nemus´ı m´ıt k dispozici posledn´ı verzi JDK, a applet mu nemus´ı fungovat. Aplety lze vytv´aˇret nad grafick´ ym rozhran´ım AWT i Swing. Rozhran´ı AWT je podporov´ano vˇsemi prohl´ıˇzeˇci, o rozhran´ı Swing to neplat´ı. Navzdory naˇs´ım snah´ am bude v kaˇzd´em prohl´ıˇzeˇci aplet vypadat trochu jinak. V t´eto kapitole se budeme zab´ yvat pouze aplety vytvoˇren´ ymi v grafick´em rozhran´ı Swing. Applety maj´ı nˇekter´e zaj´ımav´e vlastnosti: mohou pˇrehr´ avat multimedi´ aln´ı soubory, mohou volat veˇrejn´e metody jin´ ych applet˚ u um´ıstˇen´ ych na stejn´e WWW stranˇe.
11.1
Struktura appletu
Aplet m˚ uˇze b´ yt tvoˇren jednou nebo v´ıce tˇr´ıdami, v´ ychoz´ı tˇr´ıda je odvozen´a od tˇr´ıdy javax.Swing.JApplet. Opˇet plat´ı z´asada, ˇze jm´eno tˇr´ıdy mus´ı b´ yt totoˇzn´e se jm´enem souboru, ve kter´em je tˇr´ıda uloˇzena. Instance tˇr´ıdy JApplet pˇredstavuje pr´ azdn´ y formul´ aˇr, na nˇej mohou b´ yt pˇrid´av´any dalˇs´ı komponenty. Applet m´a podobnou strukturu jako ”bˇeˇzn´ y” program, liˇs´ı se na “prvn´ı pohled” t´ım, ˇze nemus´ı obsahovat metodu main(). Odliˇsnost´ı je vˇsak v´ıce, jak si ˇcasem uk´ aˇzeme.
11.1.1
ˇ Zivotn´ ı cyklus appletu
Aplet se v pr˚ ubˇehu sv´eho bˇehu dost´ av´ a do nˇekolika stav˚ u, kter´e jsou doprov´azeny vol´an´ım nˇekter´ ych speci´aln´ıch metod. Tyto stavy jsou ovlivnˇeny nikoliv appletem samotn´ ym, ale prohl´ıˇzeˇcem. B´ yvaj´ı oznaˇcov´any
161
KAPITOLA 11. APLETY liter´ arn´ım tvarem “ˇzivotn´ı cyklus” apletu. Metody jsou ve vˇetˇsinˇe pˇr´ıpad˚ u deklarov´ any jako public, uˇzivatelem by mˇely b´ yt pˇredefinov´ any. Konstruktor. Konstruktor apletu je vol´ an pot´e, co byla naˇctena www str´ anka s apletem. Konstruktory nejsou v appletech t´emˇeˇr pouˇz´ıv´ any, jejich funkce nahrazuj´ı jin´e metody, napˇr. init(). metoda init(). Nejd˚ uleˇzitˇejˇs´ı metoda, je vol´ ana po vykon´ an´ı konstruktoru. Jej´ım c´ılem je proveden´ı inicializace apletu, supluje tedy funkci konstruktoru. K´ od v n´ı by mˇel b´ yt chr´ anˇen pro pˇr´ıpad vzniku v´ yjimky, nejˇcastˇeji je pouˇz´ıv´ ana konstrukce try-catch. Metoda je vol´ ana pro aplet pouze jedenkr´ at. Kaˇzd´ y applet by mˇel obsahovat metodu init(). metoda start(). Po proveden´ı metody init() je applet spuˇstˇen metodou start(). Metoda je vykon´ana vˇzdy, kdyˇz se aplet stane v oknˇe prohl´ıˇzeˇce viditeln´ y. Na rozd´ıl od pˇredchoz´ı metody m˚ uˇze b´ yt pro aplet vol´ ana opakovanˇe. ˇ metoda stop(). Cinnost apletu je metodou stop ukonˇcena. Dojde k tomu, kdyˇz aplet pˇrestane b´ yt v oknˇe prohl´ıˇzeˇce viditeln´ y. Pokud se aplet stane opˇet viditeln´ y, je vykon´ ana metoda start(), kter´ a aplet spust´ı. Metoda start() m˚ uˇze b´ yt pro aplet vol´ ana opakovanˇe, je vlastnˇe protˇejˇskem metody stop(). Pouˇz´ıv´a se ˇcasto v pˇr´ıpadˇe, kdy applet prov´ ad´ı v´ ypoˇcetnˇe n´ aroˇcn´e ˇcinnosti, napˇr. animace. metoda destroy(). Metoda je vol´ ana pˇri uvolnˇen´ım apletu z pamˇeti, m´ a podobnou funkci jako destruktor. Pro aplet je vol´ ana pouze jednou. metoda paint(Graphics g). Jej´ı funkce je podobn´ a jako v pˇr´ıpadˇe metody paintComponent(). Metoda je vol´ ana v pˇr´ıpadˇe, kdy je nutno pˇrekreslit obsah okna. Na objekt tˇr´ıdy Graphics lze kreslit bˇeˇzn´ ymi metodami. metoda jbInit(). Metoda, kter´ a je deklarov´ ana jako priv´ atn´ı, je pouˇz´ıv´ ana pˇri inicializaci komponent.
11.2
Tvorba appletu
V t´eto kapitole se budeme snaˇzit vytvoˇrit jednoduch´ y aplet, kter´ y provede seˇcten´ı dvou ˇc´ısel zadan´ ych do textfield˚ u. Spuˇstˇen´ı v´ ypoˇctu se provede stiskem tlaˇc´ıtka; jedn´ a se o modifikaci pˇr´ıkladu z kapitoly 1.8.5. Vytvoˇr´ıme tˇr´ıdu AppletScitani, kter´ a bude potomkem tˇr´ıdy JApplet. Datov´e poloˇzky tˇr´ıdy budou stejn´e. public class AppletScitani extebds JApplet{ private int prvni, druhe, soucet; private JLabel l1,l2,l3; private JTextField t1, t2; private JButton b; public Form() {}; Vˇsimnˇeme si, ˇze v konstruktoru nen´ı um´ıstˇen ˇz´ adn´ y v´ ykonn´ y k´ od. Vytvoˇr´ıme metodu init(), kter´ a bude obsahovat v´ ykonn´ y k´ od um´ıstˇen´ y v chr´ anˇen´em bloku try-catch pro pˇr´ıpad, ˇze by inicializace neprobˇehla u ´spˇeˇsnˇe. Velikost appletu je nastavena na 200 x 100 pixel˚ u.
KAPITOLA 11. APLETY public void init() { try { this.setSize(200,100); this.setLayout(new GridLayout(3,2)); l1=new JLabel("Prvni cislo"); l2=new JLabel("Druhe cislo"); t1=new JTextField(); t2=new JTextField(); t1.setText("0"); t2.setText("0"); b=new JButton("Soucet"); l3=new JLabel(); this.getContentPane().add(l1); this.getContentPane().add(l2); this.getContentPane().add(t1); this.getContentPane().add(t2); this.getContentPane().add(b); this.getContentPane().add(l3); this.setVisible(true); Za pouˇzit´ı metody setText() inicializujeme v´ ychoz´ı hodnoty v textfieldech na 0, v opaˇcn´em pˇr´ıpadˇe by mohlo doj´ıt k v´ yjimce. Pr´ ace s ud´ alostmi bude ˇreˇsena stejnˇe. Hodnoty obou sˇc´ıtanc˚ u budou z´ısk´ any pˇri ud´alosti FocusEvent, vlastn´ı sˇc´ıt´ an´ı probˇehne po stisku tlaˇc´ıtka, v´ ysledn´ y text bude zobrazen v labelu. t1.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { prvniZadej(e); } public void focusGained(FocusEvent e){}; }); t2.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { druheZadej(e); } public void focusGained(FocusEvent e){}; }); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { soucet(e); } }); } catch (Exception e) { e.printStackTrace(); } } public void prvniZadej(FocusEvent e) {
KAPITOLA 11. APLETY this.prvni=Integer.parseInt(t1.getText()); } public void druheZadej(FocusEvent e) { this.druhe=Integer.parseInt(t2.getText()); } public void soucet(ActionEvent e) { soucet=this.prvni+this.druhe; l3.setText(String.valueOf(soucet)); } } Vˇsimli jsme si, ˇze oproti ”klasick´e” aplikaci se zdrojov´ y k´ od takˇrka neliˇs´ı. Pouze k´ od, kter´ y byl p˚ uvodnˇe um´ıstˇen v konstruktoru, pˇreˇsel do metody init(). V naˇsem pˇr´ıpadˇe jsme nepouˇzili metodu stop(), applet neprov´ adˇel ˇz´ adn´e v´ ypoˇcetnˇe n´ aroˇcn´e operace.
11.3
Spuˇ stˇ en´ı appletu
Applet neobsahuje metodu main(), nem˚ uˇze b´ yt spouˇstˇen klasicky z pˇr´ıkazov´eho ˇr´ adku. Aby aplet mohl bˇeˇzet, je nutn´e nejprve vytvoˇrit HTML soubor, kter´ y bude obsahovat pˇr´ıkaz pro spuˇstˇen´ı appletu. Aplet je vol´an uveden´ım n´azvu pˇreloˇzen´e tˇr´ıdy z tagu <APPLET>, mus´ı obsahovat nˇekter´e dalˇs´ı informace, napˇr. u ´ daje o velikosti apletu. Pokud vytv´ aˇr´ıme aplety v nˇekter´em z v´ yvojov´ ych prostˇred´ı, jsou pˇr´ısluˇsn´e HTML soubory generov´any automaticky, nemus´ıme je vytv´ aˇret “ruˇcnˇe”. Jm´eno HTML souboru m˚ uˇze b´ yt libovoln´e, nijak nesouvis´ı s apletem. V jednom souboru m˚ uˇze b´ yt v´ıce neˇz jeden aplet. N´ asleduj´ıc´ı pˇr´ıklad ukazuje jednoduchou WWW str´ anku s k´ odem pro spuˇstˇen´ı apletu. <TITLE> Sˇ c´ ıt´ an´ ı dvou ˇ c´ ısel. Applet prov´ adˇ ej´ ıc´ ı sˇ c´ ıt´ an´ ı dvou ˇ c´ ısel.
<APPLET CODEBASE="." CODE="AppletScitani.class" NAME="Muj prvni applet" WIDTH=200 HEIGHT=100 HSPACE=0 VSPACE=0 ALIGN=left Popisem HTML k´ odu se zab´ yvat nebudeme, uvedeme v´ yznam jednotliv´ ych poloˇzek um´ıstˇen´ ych uvnitˇr tagu <APPLET>. Vˇsechny poloˇzky nejsou povinn´e, kaˇzd´ y applet by mˇel obsahovat poloˇzky , , <WIDTH>, .
KAPITOLA 11. APLETY CODEBASE. Tato poloˇzka obsahuje cestu (ve formˇe URL), ve kter´e se nach´ azej´ı jednotliv´e pˇreloˇzen´e tˇr´ıdy (popˇr. JAR soubory). Nemusej´ı b´ yt um´ıstˇeny standardnˇe, tj. ve stejn´em podadres´ aˇri jako HTML soubory, ale v libovoln´e sloˇzce. Pokud se nach´ azej´ı ve stejn´e sloˇzce, pouˇzijeme oznaˇcen´ı aktu´ aln´ıho adres´ aˇre ”.”, nebo tuto poloˇzku m˚ uˇzeme vynechat. Jednotliv´e u ´rovnˇe cesty jsou oddˇelov´ any znakem /. CODE. Pˇredstavuje jm´eno tˇr´ıdy appletu, kter´ a bude spuˇstˇena. Standardnˇe se jedn´ a o tˇr´ıdu, kter´ a je potomkem tˇr´ıdy JApplet. NAME. Pˇredstavuje jm´eno apletu, lze vyuˇz´ıt pˇri vz´ ajemn´e komunikaci dvou aplet˚ u. ˇıˇrka okna apletu v pixelech. WIDTH. S´ ˇıˇrka okna apletu v pixelech. HEIGHT. S´ HSPACE. Odsazen´ı apletu v pixelech zleva. VSPACE. Odsazen´ı apletu v pixelech shora. ALIGN. Zarovn´ an´ı apletu vzhledem k WWW str´ ance. K dispozici jsou n´ asleduj´ıc´ı moˇznosti: left, right, top, bottom,absmiddle. PARAM. Aplet m˚ uˇze naˇc´ıtat extern´ı parametry a jejich hodnoty. K dispozici jsou n´ asleduj´ıc´ı hodnoty: NAME a VALUE. Jejich naˇcten´ı je prov´ adˇeno z vlastn´ıho appletu metodou getParametr(). K´ od v tagu <APPLET>. Naˇcten´ım parametru z´ısk´ ame jeho hodnotu, k´ od ve vlastn´ım appletu vypad´ a takto. String filename=getParametr(file); ALT. Text, kter´ y je zobrazen v pˇr´ıpadˇe, kdy prohl´ıˇzeˇc nem´ a moˇznost spouˇstˇet aplety. ARCHIVE. N´azev JAR archivu (viz d´ ale). Tento parametr se ˇcasto pouˇz´ıv´ a pouˇz´ıv´ a u aplet˚ u pracuj´ıc´ıch s GUI.
11.3.1
Java archivy
Zkratka JAR pˇredstavuje Java Archiv. Pˇredstavuje zp˚ usob distribuce soubor˚ u *.class, kter´e jsou algoritmem ZIP zkomprimov´ any do jednoho souboru. Souˇc´ ast´ı JAR mohou b´ yt i dalˇs´ı soubory, napˇr. rastry ˇci multimedi´ aln´ı soubory, konfiguraˇcn´ı soubory, atd... Pouˇz´ıv´ an´ı archiv˚ u pˇrin´ aˇs´ı nˇekolik v´ yhod, velice struˇcnˇe se s nimi sezn´ am´ıme: 1. Zmenˇsen´ı velikosti dat. Tato v´ yhoda se projev´ı zejm´ena u aplet˚ u, kdy pˇren´ aˇs´ıme menˇs´ı mnoˇzstv´ı dat. Vyuˇzit´ım komprese se velikost souboru sn´ıˇz´ı cca. na polovinu, d˚ usledkem je rychlejˇs´ı naˇcten´ı appletu.
KAPITOLA 11. APLETY 2. Vˇsechny potˇrebn´e soubory jsou ”sbaleny” do jednoho archivu. T´ yk´ a se to zejm´ena pˇr´ıpad˚ u, kdy program vyuˇz´ıv´a anonymn´ı vnitˇrn´ı tˇr´ıdy, tj. pˇri pouˇzit´ı grafick´eho rozhran´ı. Pˇrekladem takov´eho programu vznik´a “vˇetˇs´ı” poˇcet pˇreloˇzen´ ych soubor˚ u class. 3. Jm´eno Java archivu nen´ı z´ avisl´e na n´ azvu jednotliv´ ych tˇr´ıd, m˚ uˇze b´ yt pojmenov´ an podle naˇsich pˇredstav. 4. Jednoduch´e spouˇstˇen´ı programu. Pro spuˇstˇen´ı Java archivu nen´ı nutno tento archiv rozbalovat, lze ho spustit jedin´ ym pˇr´ıkazem. Archiv s n´ azvem Pokus lze spustit bud’ dvojklikem na n´ azev archivu nebo z pˇr´ıkazov´e ˇr´ adky takto: java -jar "Pokus.jar" Popiˇsme pro u ´plnost i druhou variantu spuˇstˇen´ı programu: soubory obsaˇzen´e v Java archivu nejprve rozbal´ıme a n´ aslednˇe spust´ıme. Tento postup vˇsak nen´ı v praxi pouˇz´ıv´ an, je ponˇekud nepohodln´ y. Uved’me pˇrehled pˇr´ıkaz˚ u pouˇz´ıvan´ ych pro pr´ aci s JAR soubory. Vytvoˇ ren´ı archivu. Pro vytvoˇren´ı archivu je pouˇzit pˇr´ıkaz java -jar cf nazev_archivu jmena_souboru N´ azev archivu mus´ı b´ yt uveden vˇcetnˇe pˇr´ıpony jar. Jm´ena soubor˚ u mohou b´ yt oddˇelena ˇc´ arkami nebo lze pouˇz´ıt masku souboru ve tvaru hvˇezdiˇckov´e konvence. java -jar cf archiv.jar main.class,form.class java -jar cf archiv.jar *.class Prvn´ı pˇr´ıkaz vytvoˇr´ı archiv ze dvou zadan´ ych soubor˚ u, druh´ y ze vˇsech soubor˚ u s pˇr´ıponou *.class v aktu´aln´ım podadres´ aˇri. Rozbalen´ı archivu. Rozbalen´ı archivu vˇcetnˇe automatick´eho vytvoˇren´ı vˇsech potˇrebn´ ych podadres´aˇr˚ u lze prov´est pˇr´ıkazem java -jar xf nazev_archivu V´ ypis soubor˚ u v archivu. Soubory a adres´ aˇre obsaˇzen´e v archivu lze vypsat pˇr´ıkazem java -jar tf nazev_archivu
11.3.2
JAR soubory a aplety
Java applety obsahuj´ıc´ı komponenty GUI jsou ˇcasto distribuov´ any ve formˇe JAR soubor˚ u. V takov´em pˇr´ıpadˇe je do HTML souboru nutno pˇridat sekci ARCHIVE s uveden´ım jm´ena archivu. Poloˇzka CODE bude st´ ale obsahovat spouˇstˇec´ı tˇr´ıdu apletu. CODE="AppletScitani.class" ARCHIVE="archiv.jar" Archiv se m˚ uˇze nach´ azet i v nˇekter´em z podadres´ aˇr˚ u, mus´ıme k nˇemu tedy uv´est cestu CODE="AppletScitani.class" ARCHIVE="applets/archiv.jar"
KAPITOLA 11. APLETY Pozor ! Pokud vytv´ aˇr´ıme aplet za pouˇzit´ı GUI builder˚ u, pˇri n´ avrhu metodou drag and drop jsou mnohdy pouˇz´ıv´any nestandardn´ı konstrukce ˇci komponenty, pˇr´ısluˇsn´e knihovny mus´ı b´ yt pˇripojeny k distribuovan´e aplikace, v opaˇcn´em pˇr´ıpadˇe by neˇsla spustit. Typick´ ym pˇr´ıkladem je v´ yvojov´e prostˇred´ı NetBeans, kter´e vyuˇz´ıv´ a tzv. swing layout. K naˇs´ı aplikaci mus´ıme pˇripojit archiv swing-layout-1.0.jar. Zpravidla ho pˇribalujeme do stejn´e sloˇzky, ve kter´e se nach´ azej´ı pˇreloˇzen´e soubory. ARCHIVE="swing-layout-1.0.jar" Spuˇ stˇ en´ı appletu Applet spust´ıme prostˇrednictv´ım pˇr´ısluˇsn´eho HTML souboru. Pokud jsme vˇsechny potˇrebn´e kroky vykonali spr´ avnˇe, v´ ysledek m˚ uˇze vypadat takto.
Obr´ azek 11.1: Uk´ azka apletu v prohl´ıˇzeˇci Opera.
Pokud jsme nˇekde udˇelali chybu (nejˇcastˇeji ˇspatn´e zad´ an´ı cesty k apletu), v´ ysledek bude vypadat takto:
Obr´ azek 11.2: Probl´em pˇri pr´ aci s apletem.
11.3.3
Applet viewer
Pr´ ace s appletem ve webov´em prohl´ıˇzeˇci nen´ı pˇr´ıliˇs pohodln´ a. Jej´ı nejvˇetˇs´ı nev´ yhodou je fakt, ˇze pˇr´ıpadn´e zmˇeny ve zdrojov´em k´ odu appletu se v prohl´ıˇzeˇci neprojev´ı ani pˇri opakovan´em naˇcten´ı www strany s appletem. Prohl´ıˇzeˇc tedy mus´ıme restartovat. Existuje aplikace, kter´ a se pouˇz´ıv´ a pro zobrazov´ an´ı applet˚ u s n´azvem appletviewer. Appletviewer se pouˇz´ıv´ a pro zobrazen´ı appletu uveden´eho HTML k´ odu str´ anky, veˇsker´ y HTML k´ od strany ignoruje. Spust´ıme ho n´ asleduj´ıc´ım pˇr´ıkazem appletviewer nazev_html_souboru.
KAPITOLA 11. APLETY Applet viewer se tedy pouˇz´ıv´ a jako ladic´ı n´ astroj pro zobrazov´ an´ı applet˚ u v pr˚ ubˇehu jejich n´ avrhu. Aplet zobrazen´ y v applet vieweru vypad´ a takto:
Obr´ azek 11.3: Aplet prov´ adˇej´ıc´ı souˇcer dvou ˇc´ısel. Appletviewer m˚ uˇzeme oˇs´ alit. Pokud do zdrojov´eho k´ odu pˇrid´ ame na jeho zaˇc´ atek ve formˇe jednoˇr´ adkov´ ych koment´ aˇr˚ u n´ asleduj´ıc´ı text //<APPLET //CODEBASE="." //CODE="AppletScitani.class" //NAME="Muj prvni applet" //WIDTH=200 //HEIGHT=100 //HSPACE=0 //VSPACE=0 //ALIGN=left // budeme moci appletviewererem spouˇstˇet pˇr´ımo soubor AppletScitani.class.
11.3.4
Spouˇ stˇ en´ı appletu jako aplikace
ˇ Casto poˇzadujeme, aby program bylo moˇzno spustit jako aplet i aplikaci. Tento poˇzadavek lze vyˇreˇsit velmi jednoduˇse, do appletu pˇrid´ ame metodu main(). Tato metoda je appletem ignorov´ ana, z´ aroveˇ n vˇsak umoˇzn´ı spouˇstˇen´ı apletu jako aplikace. Je vhodn´e pˇripomenout, ˇze aplet pro kreslen´ı vyuˇz´ıv´ a metodu paint(), aplikace paintComponent(). Pokus´ıme se vytvoˇrit aplikaci generuj´ıc´ı graf funkce sinus ve formˇe apletu i aplikace. public class AppletSinus extends JApplet { public AppletSinus() {} public void initcomponents() {} public void paint(Graphics g) { double step=0.1, x,y,xo,yo; x=100/3; xo=x; y=0; yo=0; for (double i=0;i<4*Math.PI;i=i+step) { y=i*200/8; x=100/3-Math.sin(i)*200/8;
KAPITOLA 11. APLETY g.drawLine((int)yo,(int)xo,(int)y,(int)x); xo=x; yo=y; } } public static void main(String[] args) { JFrame f=new JFrame(); f.setTitle("Sinus"); f.setVisible(true); f.getContentPane().add(new Draw()) } } Vˇsimnˇeme si, ˇze v tomto pˇr´ıpadˇe metoda init() neobsahuje ˇz´ adn´ y k´ od. Nen´ı potˇreba vytv´ aˇret ˇz´ adn´e komponenty ani oˇsetˇrovat ud´ alosti. Tˇr´ıda Draw prov´ adˇej´ıc´ı kreslen´ı vypad´ a takto: public class Draw extends JComponent{ public void paintComponent(Graphics g) { double step=0.1, x,y,xo,yo; x=100/3; xo=x; y=0; yo=0; for (double i=0;i<4*Math.PI;i=i+step) { y=i*200/8; x=100/3-Math.sin(i)*200/8; g.drawLine((int)yo,(int)xo,(int)y,(int)x); xo=x; yo=y; } } } Applet i aplikaci si m˚ uˇzeme prohl´ednout na n´ asleduj´ıc´ıch obr´ azk´ ach.
Obr´ azek 11.4: Aplet generuj´ıc´ı sinusoidu. Vlevo v aplet vieweru, vpravo v prohl´ıˇzeˇci.
Kapitola 12
Java a datab´ aze Podobnˇe, jako vˇetˇsina vyˇsˇs´ıch jazyk˚ u, um´ı i Java pracovat s datab´azov´ ymi syst´emy. K tomu, abychom mohli z Javy pˇristupovat k datab´ azov´emu serveru, ukl´adat a naˇc´ıtat data, potˇrebujeme JDBC (Java DataBase Connectivity). JDBC je API pro program´ atory v programovac´ım jazyku Java, kter´e definuje jednotn´e rozhran´ı pro pˇr´ıstup k relaˇcn´ım datab´ azov´ ym syst´em˚ um. JDBC je souˇc´ast´ı Javy SE od JDK 1.1. Pro pˇr´ıstup ke konkr´etn´ımu datab´ azov´emu serveru je potˇreba JDBC ovladaˇc, kter´ y poskytuje tv˚ urce datab´azov´e platformy.
K pˇr´ıstupu k jednotliv´ ym datab´ azov´ ym server˚ um n´am tedy slouˇz´ı JDBC ovladaˇce, kter´e jsou specifick´e pro kaˇzdou datab´ azovou platformu: * MySQL: com.mysql.jdbc.Driver, * Oracle: oracle.jdbc.driver.OracleDriver, * MS Access: sun.jdbc.odbc.JdbcOdbcDriver, a pˇripojovac´ı ˇretˇezec, kter´ y je podobnˇe jako ovladaˇc z´avisl´ y na pouˇzit´e datb´azov´e platformˇe: * MySQL: jdbc:mysql://server/jm´ eno_datab´ aze?characterEncoding=UTF-8 * Oracle: jdbc:oracle:thin:@server:port:jm´ eno_datab´ aze
Obr´ azek 12.1: Sch´ema komunikace Javy s datab´ azov´ym serverem.
170
´ KAPITOLA 12. JAVA A DATABAZE * MS Access: jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)}; DBQ="[soubor datab´ aze]; DriverID=22; READONLY=false} Nyn´ı se pokus´ıme vytvoˇrit jednoduchou konzolovou aplikaci, kter´ a bude pracovat s datab´ azov´ ym syst´emem. ´ C´ılem aplikace bude spr´ ava (ukl´ ad´ an´ı, maz´ an´ı, atd.) bod˚ u definovan´ ych pravo´ uhl´ ymi souˇradnicemi x, y. Ulo1 ˇziˇstˇem souˇradnic nebudou datov´e poloˇzky tˇr´ıdy, ale datab´ azov´ y syst´em. MySQL bude pro tuto jednoduchou aplikaci plnˇe dostaˇcuj´ıc´ı. Pro komunikaci s datab´ azov´ ym serverem budeme potˇrebovat vhodn´ y ovladaˇc. Ovladaˇce jsou k dispozici na webov´e adrese http://dev.mysql.com/downloads/connector/. Pro naˇsi aplikaci je vhodn´ y ovladaˇc Connector/J 5.0, kter´ y je tˇreba st´ ahnout a zaˇclenit do aplikace. Pˇ rid´ an´ı ovladaˇ ce. Pˇrid´ an´ı a zaˇclenˇen´ı ovladaˇce pro konunikace s datab´ azov´ ym serverem lze prov´est kliknut´ım prav´eho tlaˇc´ıtka na n´ azev projektu a poloˇzku Properties. V z´ aloˇzce Libraries pˇrid´ ame pomoc´ı tlaˇc´ıtka Add JAR/Folder soubor ovladaˇce pro komunikaci MySQL s Javou. V tomto pˇr´ıpadˇe se jedn´ a o soubor mysql-connector-java-5.0.7-bin.jar. Potvrzen´ım se vybran´ a knihovna ovladaˇce pˇrid´ a do CLASSPATH projektu. Bez knihovny ovladaˇce pˇridan´e do CLASSPATH se n´ am nepodaˇr´ı pˇripojit k datab´ azov´emu serveru MySQL!2
12.1
Komunikace s datab´ azov´ ym syst´ emem
Z´ akladem aplikace bude komunikace s datab´ azov´ ym syst´emem MySQL. Nadefinujeme tˇr´ıdu MySQLDatabase, kter´ a bude m´ıt nˇekolik promˇenn´ ych: server, db, user, password a encoding. Do tˇechto promˇenn´ ych budeme ukl´ adat parametry konstruktoru tˇr´ıdy. Pokud je MySQL nainstalov´ ano na lok´ aln´ım poˇc´ıtaˇci, bude se serverem localhost nebo IP adresa 127.0.0.1. Pokud MySQL na lok´ aln´ım poˇc´ıtaˇci nainstalov´ ano nen´ı, je tˇreba zadat IP adresu nebo n´ azev vzd´ alen´eho poˇc´ıtaˇce, na kter´em je MySQL nainstalov´ ano. Mus´ıme t´eˇz nadefinovat datab´ azi, ke kter´e se budeme pˇripojovat, tu budeme ukl´ adat do promˇenn´e db. User a password reprezentuj´ı pˇrihlaˇsovac´ı u ´ daje a encoding umoˇzn ˇuje nastavit k´ odov´ an´ı, v kter´em budeme komunikovat s datab´ az´ı (t´ yk´a se pr´ ace s ˇretˇezci). public class MySQLDatabase { private private private private private
String String String String String
server; db; user; password; encoding;
public MySQLDatabase(String server, String db, String user, String password, String encoding) { this.server = server; this.db = db; this.user = user; this.password = password; this.encoding = encoding; 1 Jde o malou” volnˇ e staˇ zitelnou open-source datab´ azovou platformu. Souˇ c´ ast´ı instalace je nav´ıc velmi ˇsikovn´ y administr´ ator ” phpMyAdmin. 2 Uveden´ y postup plat´ı pouze pro v´ yvojov´ e prostˇred´ı NetBeans. V ostatn´ıch v´ yvojov´ ych prostˇred´ıch je vˇsak postup vˇ etˇsinou velmi podobn´ y.
´ KAPITOLA 12. JAVA A DATABAZE } } Konstruktor je velmi jednoduch´ y, slouˇz´ı k inicializaci datov´ ych poloˇzek tˇr´ıdy. Pokus´ıme se nyn´ı definovat metodu, pomoc´ı kter´e bychom se mohli pˇripojit k MySQL. Tˇr´ıdy a metody pro pr´ aci s datab´ azov´ ymi syst´emy jsou k dispozici v bal´ıˇcku java.sql. Souˇc´ ast´ı tohoto bal´ıˇcku je i tˇr´ıda Connection, jej´ıˇz instanci bude vracet metoda getConnectionToMySQL(). Tato metoda tedy nav´ aˇze kontakt s datab´ azov´ ym serverem a vr´ at´ı kontakt v podobˇe objektu tˇr´ıdy Connection. public Connection getConnectionToMySQL() { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver").newInstance(); conn = DriverManager.getConnection("jdbc:mysql://"+ this.server +"/" + this.db + "?characterEncoding=" + this.password + "&user=" + this.user + "&password=" + this.password); } catch (SQLException ex) { ex.printStackTrace(); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } return conn; } Vˇsimnˇeme si, kolik v´ yjimek je zapotˇreb´ı oˇsetˇ rit. V´ yjimka SQLException se t´ yk´ a vˇetˇsiny tˇr´ıd z bal´ıˇcku java.sql. V´ yjimky ClassNotFoundException, InstantiationException, IllegalAccessException se t´ ykaj´ı ovladaˇce JDBC.
12.2
Z´ısk´ av´ an´ı metadat o datab´ azi
Abychom co nejl´epe oˇsetˇrili ukl´ ad´ an´ı bod˚ u do datab´ aze, vytvoˇr´ıme si ve tˇr´ıdˇe MySQLDatabase metodu, kter´a bude zjiˇst’ovat, zda v datab´ azi existuje tabulka dan´eho jm´ena. Metoda existTable() bude vracet bud’ hodnotu true nebo false a parametrem bude promˇenn´ a tableName typu String. public boolean existTable(String tableName) { Connection conn = null; ResultSet tables; boolean existuje = false; try { conn = getConnectionToMySQL(); DatabaseMetaData dbm = conn.getMetaData(); tables = dbm.getTables(null, null, tableName, null); if (tables.next()) {
´ KAPITOLA 12. JAVA A DATABAZE existuje = true; } else { existuje = false; } } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException ex) { ex.printStackTrace(); } conn = null; } } return existuje; } Metoda existTable() se nejprve pomoc´ı metody getConnectionToMySQL() pˇripoj´ı k MySQL. Pot´e vytvoˇr´ı objekt tˇr´ıdy DatabaseMetaData pomoc´ı metody getMetaData(). Jak n´ azev napov´ıd´ a tˇr´ıda DatabaseMetaData je urˇcena pro z´ısk´ av´ an´ı informac´ı o datab´ azi, ke kter´e jsme pˇripojeni. Metoda getTables() zjiˇst’uje, zda se v datab´ azi nal´ez´ a tabulka, dan´ a parametrem metody. Tˇr´ıda DatabaseMetaData ale obsahuje dalˇs´ı uˇziteˇcn´e metody: • getAttributes() - metoda vrac´ı seznam atribut˚ u dan´e tabulky, • getPrimaryKeys() - metoda vrac´ı seznam atribut˚ u dan´e tabulky, kter´e jsou z´ aroveˇ n prim´ arn´ı kl´ıˇce, • supportsTransactions() - metoda zjist´ı, zda datab´ azov´ y syst´em podporuje transakce, • supportsSavepoints() - metoda vrac´ı hodnotu true, pokud datab´ azov´ y syst´em pˇri ne´ uspˇeˇsn´e transakci podporuje n´ avrat do nˇejak´eho stavu (nastaven´eho pomoc´ı bodu n´ avratu - savepointu) v pr˚ ubˇehu transakce. T´ımto m´ ame vytvoˇrenu tˇr´ıdy MySQLDatabase, kter´ a n´ am bude usnadˇ novat tvorbu tˇr´ıdy bod˚ u.
12.3
Vkl´ ad´ an´ı dat do datab´ aze
Tˇr´ıda Point bude obsahovat dvˇe datov´e poloˇzky tˇr´ıdy, explicitn´ı konstruktor a nˇekolik metod. Datov´ ymi poloˇzkami instance budou: private int ID_bodu; private MySQLDatabase db = new MySQLDatabase("localhost", "points", "root", "", "UTF-8");
´ KAPITOLA 12. JAVA A DATABAZE V promˇenn´e ID bodu bude uloˇzena hodnota jedineˇcn´ a pro kaˇzd´ y bod a my ji podle t´eto promˇenn´e v datab´azi bod˚ u jednoznaˇcnˇe identifikujeme. Tvorbu tˇechto jedineˇcn´ ych hodnot nech´ ame na stranˇe datab´ aze: ID_bodu INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (ID_bodu) T´ımto se n´am pro kaˇzd´ y bod v datab´ azi vytvoˇr´ı jedineˇcn´e ˇc´ıslo pˇredstavuj´ıc´ı identifik´ ator bodu. Abychom ale toto ˇc´ıslo mohli uloˇzit do datov´e poloˇzky tˇr´ıdy, je tˇreba pouˇz´ıt metodu tˇr´ıdy Statement se dvˇema parametry: stmt.executeUpdate("...", Statement.RETURN_GENERATED_KEYS); rset = stmt.getGeneratedKeys(); rset.next(); this.ID_bodu = rset.getInt(1); Prvn´ım parametrem je SQL pˇr´ıkaz, druh´ ym je objekt tˇr´ıdy Statement. Pomoc´ı metody getGeneratedKeys() umoˇzn ˇuje n´ avrat ResultSetu s automaticky vygenerovan´ ymi hodnotami. Konstruktor tˇr´ıdy Point m´a tˇri parametry - souˇradnice bodu x, y, z. Tyto souˇradnice jsou pˇr´ımo v tˇele konstruktoru ukl´ ad´ any do datab´ aze: public Point(double x, double y, double z) { // testovani, zda existuje tabulka ’body’, pokud ne, jeji vytvoreni if (db.existTable("body")) { Connection conn = null; Statement stmt = null; ResultSet rset = null; try { conn = db.getConnectionToMySQL(); stmt = conn.createStatement(); stmt.executeUpdate("INSERT INTO body (X, Y, Z) VALUES (" + x + ", " + y + ", " + z + ");", Statement.RETURN_GENERATED_KEYS); rset = stmt.getGeneratedKeys(); rset.next(); this.ID_bodu = rset.getInt(1); } catch (SQLException ex) { ex.printStackTrace(); } finally { try { conn.close(); stmt.close(); rset.close(); } catch (SQLException ex) { ex.printStackTrace(); } } } else { Connection conn = null; Statement stmt = null; ResultSet rset = null;
´ KAPITOLA 12. JAVA A DATABAZE try { conn = db.getConnectionToMySQL(); stmt = conn.createStatement(); stmt.executeUpdate("CREATE TABLE body (ID_bodu INTEGER NOT NULL AUTO_INCREMENT, X DOUBLE PRECISION, Y DOUBLE PRECISION, Z DOUBLE PRECISION, Datum_zalozeni TIMESTAMP NOT NULL, Popis VARCHAR(254), PRIMARY KEY (ID_bodu))"); stmt.executeUpdate("INSERT INTO body (X, Y, Z) VALUES (" + x + ", " + y + ", " + z + ");", Statement.RETURN_GENERATED_KEYS); rset = stmt.getGeneratedKeys(); rset.next(); this.ID_bodu = rset.getInt(1); } catch (SQLException ex) { ex.printStackTrace(); } finally { try { conn.close(); stmt.close(); rset.close(); } catch (SQLException ex) { ex.printStackTrace(); } } } } Tˇelo konstruktoru se hned na zaˇc´ atku vˇetv´ı na dva pˇr´ıpady. Vyuˇz´ıv´ a existTable() tˇr´ıdy MySQLDatabase ke zjiˇstˇen´ı, zda v datab´ azi points existuje tabulka body, do n´ıˇz se budou ukl´ adat souˇradnice vytvoˇren´eho bodu. Pokud tabulka existuje, je nav´ az´ ano pˇripojen´ı k datab´ azi a uloˇzeno do objektu conn. Pomoc´ı tohoto objektu a metody createStatement() je pot´e vytvoˇren objekt stmt tˇr´ıdy Statement. Metody t´eto tˇr´ıdy umoˇzn ˇ uj´ı komunikovat s datab´ az´ı pomoc´ı SQL pˇr´ıkaz˚ u. Tˇr´ıda Statement obsahuje nˇekolik z´ akladn´ıch metod: • executeQuery() - Metoda je urˇcena pro SQL pˇr´ıkazy, jejichˇz v´ ysledkem je relace (tabulka). N´ avratov´ ym typem je objekt typu ResultSet, pomoc´ı nˇehoˇz pot´e m˚ uˇzeme pˇristupovat k samotn´ ym dat˚ um. Pˇr´ıklad: – stmt.executeQuery("SELECT X, Y, Z FROM body WHERE ID_bodu = 2;"); • executeUpdate() - Metoda, jej´ımˇz parametrem jsou SQL pˇr´ıkazy pro vkl´ ad´ an´ı, aktualizaci a maz´an´ı z´ aznam˚ u v datab´ azi. Tato metoda t´eˇz vyhodnot´ı SQL pˇr´ıkazy pro vytv´ aˇren´ı nov´ ych tabulek ˇci zmˇen´am v jejich struktuˇre. N´ avratov´ ym typem metody executeUpdate() je integer. Pro SQL pˇr´ıkazy pro manipulaci s daty vrac´ı metoda poˇcet ovlivnˇen´ ych z´ aznam˚ u. Pro pˇr´ıkazy DDL (Data Definition Language) vrac´ı 0. Pˇr´ıklad: – stmt.executeUpdate("CREATE TABLE body (ID_bodu INTEGER);"); – stmt.executeUpdate("DELETE FROM body WHERE ID_bodu = 2;"); • execute() - Pokud nev´ıme nebo nen´ı zn´ amo, jestli SQL pˇr´ıkaz bude vracet relaci nebo poˇcet ovlivnˇen´ ych z´ aznam˚ u, m˚ uˇzeme pouˇz´ıt tuto metodu. Bude-li v´ ysledkem relace, vr´ at´ı metoda hodnotu true a relaci je moˇzn´e z´ıskat pˇr´ıkazem:
´ KAPITOLA 12. JAVA A DATABAZE – ResultSet resultSet = stmt.getResultSet(); Kdyˇz bude v´ ysledkem poˇcet ovlivnˇen´ ych z´ aznam˚ u, vr´ at´ı metoda false a poˇcet ovlivnˇen´ ych z´aznam˚ u bude k dispozici v promˇenn´e updatesCount: – int updatesCount = stmt.getUpdatesCount(); • addBatch() a executeBatch() - Tyto dvˇe metody jsou urˇceny pro d´ avkov´e zpracov´ an´ı. Pˇr´ıklad: – – – –
stmt.addBatch("DELETE FROM body WHERE ID_bodu = 2;"); stmt.addBatch("DELETE FROM body WHERE ID_bodu = 3;"); stmt.addBatch("DELETE FROM body WHERE ID_bodu = 12;"); int[] results = stmt.executeBatch();
Tˇr´ıdy Connection, Statement i ResultSet obsahuj´ı tak´e metodu close(), kter´ a uzavˇre vytvoˇren´e objekty.
12.4
V´ ybˇ er dat z datab´ aze
Pomoc´ı konstruktoru jsme tedy schopni souˇradnice vytv´ aˇren´eho bodu do datab´ aze uloˇzit. Nyn´ı se pokus´ıme uloˇzen´e souˇradnice naopak z datab´ aze pˇreˇc´ıst. K tomuto u ´ˇcelu si vytvoˇr´ıme metodu getCoordinates(), kter´a bude vracet pole typu double, v nˇemˇz budou uloˇzeny souˇradnice bodu. public double[] getCoordinates() { Connection conn = null; Statement stmt = null; ResultSet rset = null; double[] coordinates = new double[3]; try { conn = db.getConnectionToMySQL(); stmt = conn.createStatement(); rset = stmt.executeQuery("SELECT X, Y, Z FROM body WHERE ID_bodu = " + this.ID_bodu + ";"); while (rset.next()) { coordinates[0] = rset.getDouble(1); coordinates[1] = rset.getDouble(2); coordinates[2] = rset.getDouble(3); } } catch (SQLException ex) { ex.printStackTrace(); } finally { try { conn.close(); stmt.close(); rset.close(); } catch (SQLException ex) { ex.printStackTrace(); } } return coordinates; }
´ KAPITOLA 12. JAVA A DATABAZE Obdobnˇe jako u konstruktoru, i v t´eto metodˇe je tˇreba nejprve nav´ azat spojen´ı s datab´ az´ı pomoc´ı funkce getConnectionToMySQL() a vytvoˇrit objekt tˇr´ıdy Statement. Vzhledem k tomu, ˇze v´ ysledkem SQL pˇr´ıkazu bude relace, pouˇzijeme metodu executeQuery(). SQL pˇr´ıkaz vyb´ır´ a z datab´ aze vˇsechny body, kter´e se rovnaj´ı ID_bodu (hodnotu ID_bodu jsme z´ıskali a uloˇzili v konstruktoru). V´ ysledkem dotazu bude pr´ avˇe jeden z´ aznam, protoˇze ID_bodu je pro kaˇzd´ y bod jedineˇcn´e. Tento v´ ysledek uloˇz´ıme do objektu tˇr´ıdy ResultSet. K jednotliv´ ym z´ aznam˚ um pak m˚ uˇzeme pˇristupovat pomoc´ı metody next(), kter´ a vrac´ı hodnotu true a posouv´a aktu´ aln´ı ˇctec´ı pozici vˇzdy o jeden z´ aznam v relaci n´ıˇze. Pokud jiˇz v relaci nen´ı ˇz´ adn´ y dalˇs´ı z´ aznam, vr´ at´ı metoda next() hodnotu false. Jednotliv´e souˇradnice z´ısk´ ame metodou tˇr´ıdy ResultSet getDouble(). Parametrem t´eto metody je poˇrad´ı sloupce v relaci. K souˇradnic´ım lze pˇristupovat i asociativnˇe pomoc´ı stejn´e metody: coordinates[0] = rset.getDouble("X"); Metod pro z´ısk´ av´ an´ı samotn´ ych dat uloˇzen´ ych v datab´ azov´ ych tabulk´ ach m´ a tˇr´ıda ResultSet celou ˇradu. Mezi nejpouˇz´ıvanˇejˇs´ı patˇr´ı: • getString(), • getInt(), • getDate() a dalˇs´ı.
12.5
Vymaz´ an´ı dat z datab´ aze
Maz´ an´ı z´ aznam˚ u prob´ıh´ a podobn´ ym zp˚ usobem jako vkl´ ad´ an´ı nov´ ych z´ aznam˚ u. Liˇs´ı se pouze pouˇzit´ ym SQL pˇr´ıkazem. Pouˇzijeme tedy podobnˇe jako v konstruktoru metodu executeUpdate(). public void destroy() { Connection conn = null; Statement stmt = null; int smazan = 0; try { conn = db.getConnectionToMySQL(); stmt = conn.createStatement(); smazan = stmt.executeUpdate("DELETE FROM body WHERE ID_bodu = " + this.ID_bodu + ";"); } catch (SQLException ex) { ex.printStackTrace(); } finally { try { conn.close(); stmt.close(); } catch (SQLException ex) { ex.printStackTrace(); } } if (smazan == 1) {
´ KAPITOLA 12. JAVA A DATABAZE System.out.println("Bod byl uspesne smazan"); } else { System.out.println("Vymaz se nezdaril"); } } Vˇsimnˇeme si, ˇze pokud se podaˇr´ı z´ aznam z datab´ aze vymazat, vr´ at´ı metoda executeUpdate() hodnotu 1. M˚ uˇzeme tedy na konzoli vypsat, zda se vymaz´ an´ı povedlo ˇci nikoli.
12.6
Aktualizace dat v datab´ azi
Kdyˇz jsme v konstruktoru vytv´ aˇreli tabulku s body, vytvoˇrili jsme v n´ı i sloupec Popis, ale doposud jsme do nˇej ˇz´ adn´e u ´daje nevloˇzili. Nap´ıˇseme metodu, pomoc´ı n´ıˇz budeme schopni k vytvoˇren´emu bodu pˇridat koment´ aˇr. public void addComment(String comment) { Connection conn = null; Statement stmt = null; int aktualizovan = 0; try { conn = db.getConnectionToMySQL(); stmt = conn.createStatement(); aktualizovan = stmt.executeUpdate("UPDATE body SET Popis = ’" + comment + "’ WHERE ID_bodu = " + this.ID_bodu + ";"); } catch (SQLException ex) { ex.printStackTrace(); } finally { try { conn.close(); stmt.close(); } catch (SQLException ex) { ex.printStackTrace(); } } if (aktualizovan == 1) { System.out.println("Popis byl uspesne pridan"); } else { System.out.println("Popis se nezdarilo vlozit"); } } Jak vid´ıme, metoda pro pˇrid´ an´ı popisu funguje na stejn´em principu jako pˇredchoz´ı metoda. Jedin´ a odliˇsnost je v pouˇzit´em SQL pˇr´ıkazu.
´ KAPITOLA 12. JAVA A DATABAZE
12.7
Dalˇ s´ı pˇ r´ıklady
Povedlo se n´am vytvoˇrit jednoduchou aplikaci, pomoc´ı n´ıˇz m˚ uˇzeme vytv´ aˇret body pouh´ ym definov´ an´ım jejich souˇradnic. Aplikaci lze d´ ale rozˇsiˇrovat a vylepˇsovat. Metodu pro pˇrid´ an´ı koment´ aˇre k bodu jiˇz m´ ame hotovou, pokus´ıme se uloˇzen´ y koment´ aˇr vytisknout na konzoli. Pouˇzijeme k tomu metodu getComment(). public String getComment() { Connection conn = null; Statement stmt = null; ResultSet rset = null; String popis = null; try { conn = db.getConnectionToMySQL(); stmt = conn.createStatement(); stmt.execute("SET NAMES ’cp852’"); rset = stmt.executeQuery("SELECT Popis FROM body WHERE ID_bodu = " + this.ID_bodu + ";"); while (rset.next()) { popis = rset.getString(1); } } catch (SQLException ex) { ex.printStackTrace(); } finally { try { conn.close(); stmt.close(); } catch (SQLException ex) { ex.printStackTrace(); } } return popis; } Do datab´ azov´e tabulky t´eˇz ukl´ ad´ ame informaci o tom, kdy byl bod vytvoˇren. Metoda getCreationDate() dok´ aˇze tuto informaci z datab´ aze pˇreˇc´ıst a vypsat. public String getCreationDate() { Connection conn = null; Statement stmt = null; ResultSet rset = null; String datum = null; Timestamp timeStampTemp = null; try { conn = db.getConnectionToMySQL(); stmt = conn.createStatement(); rset = stmt.executeQuery("SELECT Datum_zalozeni FROM body WHERE ID_bodu = " + this.ID_bodu + ";"); while (rset.next()) { timeStampTemp = rset.getTimestamp(1);
´ KAPITOLA 12. JAVA A DATABAZE } } catch (SQLException ex) { ex.printStackTrace(); } finally { try { conn.close(); stmt.close(); rset.close(); } catch (SQLException ex) { ex.printStackTrace(); } } return timeStampTemp.toString(); }
12.8
Z´ avˇ er
Na z´ avˇer si na jednoduch´em pˇr´ıkladu uk´ aˇzeme, jak by mohla vypadat pr´ ace s vytvoˇrenou tˇr´ıdou Point. Komunikace s datab´ az´ı prob´ıh´ a na pozad´ı, uˇzivatel se o ni nemus´ı starat. Point bod2 = new Point(142.5, 1217.45, 1274.45); double[] souradnice = bod2.getCoordinates(); for (int i = 0; i < souradnice.length; i++) { System.out.print(souradnice[i]); System.out.print(" "); } System.out.println(); System.out.println(bod2.getCreationDate()); bod2.addComment("Nˇ ejak´ y koment´ aˇ r"); System.out.println(bod2.getComment()); bod2.destroy(); Na jednoduch´e konzolov´e aplikace jsme si tedy uk´ azali, ˇze pr´ ace s datab´ azov´ ym syst´emem je v Javˇe jednoduch´ a a srozumiteln´ a. Dalˇs´ı informace o Java ve spojen´ı s datab´ azov´ ymi syst´emy jsou dostupn´e napˇr´ıklad na webov´ ych str´ ank´ ach firmy Sun (http://java.sun.com/products/jdbc/learning.html).
Index FocusLost, 127 Fonty, 114 for, 38 foreground, 113 Form´ aln´ ı parametry, 43 form´ atovan´ y v´ ystup, 29 form´ atovan´ y vstup, 30 Formul´ aˇ re, 99
3D obd´ eln´ ık, 148 Abstraktn´ ı tˇ r´ ıdy, 66 Aktualizace dat v datab´ azi, 178 Anonymn´ ı vnitˇ rn´ ı tˇ r´ ıdy, 85 aplet, 161 Applet viewer, 167 Aritmetick´ e oper´ atory, 26 ArrayList, 90 AWT, 95
Garbage collector, 11 gettery, 57 Grafika, 146 GridLayout, 118
background, 113 Bajtov´ y k´ od, 10 Barvy, 112 Blok, 31 BorderLayout, 118 break, 40
Handler, 108 if-else, 34 Implementace rozhran´ ı, 78 Implementace v´ ıce rozhran´ ı, 81 Implicitn´ ı konstruktor, 53 Implicitn´ ı konverze, 24 informaˇ cn´ ı komponenty, 98 Inicializace pole, 32 Inkrementace a dekrementace, 27 Interaktivn´ ı komponenty, 98
Celoˇ c´ ıseln´ e datov´ e typy, 20 CLASSPATH, 16 content pane, 104 continue, 40 cyklus, 37 cyklus appletu, 161 D´ elka pole, 32 Dˇ ediˇ cnost, 61 Deklarace metody, 43 Detekcezmˇ en v tabulce, 138 Dialogov´ a okna, 138 do while, 39 dokumentaˇ cn´ ı koment´ aˇ re, 16 Double buffering, 147
JAR, 165 Java arch´ ıvy, 165 Javadoc, 17 JCheckBox, 121 JComboBox, 128 JDBC, 170 JDK, 9 Jednoduch´ y pˇ r´ ıkaz, 31 JFileChooser, 142 JLabel, 120 JList, 129 JPanel, 144 JRadioButton, 123 JRE, 9 JTable, 134 JTextField, 125 JVM, 10
Elipsa, 148 Eliptick´ a v´ yseˇ c, 148 Error, 70 Exception, 70 Explicitn´ ı konstruktor, 53 Explicitn´ ı konverze, 24 fin´ aln´ ı metody, 65 fin´ aln´ ı tˇ r´ ıdy, 65 FlowLayout, 117
181
INDEX Kombinov´ an´ ı v´ yjimek, 74 Komunikace s datab´ azov´ ym serverem, 171 konstanta ˇ retˇ ezcov´ a, 22 Konstruktor, 52 Kontejnerov´ e komponenty, 97 Kontejnery, 88 Konverze z´ akladn´ ıch datov´ ych typ˚ u, 25 Kop´ ırov´ an´ ı pole, 33 kvalifikace tˇ r´ ıdy, 18
poloha komponenty, 114 Polygon, 148 Polyline, 148 Polymorfismus, 67 POSITIVE INFINITY, 23 primitivn´ ı datov´ e typy, 11 Promˇ enn´ a rozhran´ ı, 80 Promˇ enn´ e tˇ r´ ıdy, 55 propagace v´ yjimky, 71
Layout managery, 105 Linie, 148 List, 89 Listener, 107 Logick´ y datov´ y typ, 22 Lok´ aln´ ı promˇ enn´ e, 45 look and feel, 101
RAD, 9 Re´ aln´ e datov´ e typy, 22 rekurze, 46 Relaˇ cn´ ı oper´ atory, 27 rodiˇ covsk´ a tˇ r´ ıda, 61 Rozhran´ ı a dˇ ediˇ cnost, 82 Ruˇ sen´ ı objekt˚ u, 52 RuntimeException, 70
Map, 92 Matematick´ e metody, 28 metodoa chr´ anˇ en´ ych blok˚ u, 72 Metody, 42, 43 Metody tˇ r´ ıdy, 56 N´ avˇ eˇ st´ ı, 36 N´ avratov´ y typ, 44 Naˇ cten´ ı rastru z lok´ aln´ ıho zdroje, 155 Naˇ cten´ ı rastru ze vzd´ alen´ eho zdroje, 156 Nastaven´ ı souborov´ e masky, 143 NEGATIVE INFINITY, 23 oˇ setˇ ren´ ı ud´ alosti, 108 Obd´ eln´ ık, 148 objekty jako parametry, 58 Odkaz this, 54 odvozen´ a tˇ r´ ıda, 62 Oper´ ator ?, 35 Pˇ red´ av´ an´ ı hodnotou, 43 Pˇ red´ av´ an´ ı odkazem, 44 pˇ redefinov´ an´ ı metody, 64 pˇ rekreslen´ ı komponenty, 147 pˇ ret´ ıˇ zen´ ı metody, 64 Pˇ retˇ eˇ zov´ an´ ı metod, 47 Pˇ retypov´ an´ ı, 24 Pˇ retypov´ an´ ı pˇ redka a potomka, 67 Pˇ riˇ razovac´ ı pˇ r´ ıkaz, 24 packages, 18 PATH, 15 podm´ ınka ´ upln´ a, 34 podm´ ınka ne´ upln´ a, 34 Pole, 31 Pole objekt˚ u, 57
Scrollov´ an´ ı seznamem, 133 Set, 91 settery, 57 ShowMessageDialog, 139 showOptionDialog, 140 Skuteˇ cn´ e parametry, 43 Sloˇ zen´ y pˇ r´ ıkaz, 31 Sm´ ıˇ sen´ e konverze, 25 Souˇ radnicov´ y syst´ em komponent, 104 Spuˇ stˇ en´ ı appletu, 164 statick´ e promˇ enn´ e, 11 Swing, 95 switch, 36 Tˇ elo tˇ r´ ıdy, 48 Tˇ r´ ıda, 47 teˇ ckov´ a notace, 50 Text, 148 Throwable, 70 Top-level komponenty, 97 TreeMap, 93 TreeSet, 92 Ud´ alostmi ˇ r´ ızen´ e programov´ an´ ı, 96 V´ ıcerozmˇ ern´ e pole, 33 V´ ybˇ er dat z datab´ aze, 176 velikost komponenty, 114 Vkl´ ad´ an´ ı dat do datab´ aze, 173 vlastn´ ı v´ yjimky, 76 Vnitˇ rn´ ı tˇ r´ ıda, 82 Vnitˇ rn´ ı tˇ r´ ıda a rozhran´ ı, 84 Vymaz´ an´ ı dat z datab´ aze, 177 Vytvoˇ ren´ ı objektu, 50
INDEX Vyvol´ an´ ı v´ yjimky, 74 while, 37 Z´ ısk´ av´ an´ ı metadat o datab´ azi, 172 Z´ akladn´ ı komponenty, 97 Zamˇ eˇ ren´ ı komponenty, 101 Znakov´ y typ, 21 Zobrazen´ ı rastru, 156
Literatura [1] Eckel B. : Mysl´ıme v jazyce Java, Grada Publishing, 2000 [2] Herout P.: Java, grafick´e uˇzivatelsk´e prostˇred´ı a ˇceˇstina, Kopp, 2001 [3] Herout P.: Uˇcebnice jazyka Java, Java, Kopp, 2001 [4] Chapman S. J.: Zaˇc´ın´ ame programovat v jazyce Java, Computer Press, 2001 [5] Pecinovsk´ y R.: Mysl´ıme objektovˇe v jazyku Java, Grada publishing, 2006 [6] Virius M.: Java pro zelen´ aˇce, Neocortex, 2001 [7] Creating a GUI with JFC/Swing, http://java.sun.com/docs/books/tutorial/uiswing/index.html
184