U₧ kdy₧ se v roce 1995 objevily prvnφ zprßvy o Jav∞, bylo mi jasnΘ, ₧e mne tento jazyk nemine, a nem²lil jsem se. Jeho syntaxe se na prvnφ pohled velice podobß jazyku C++, chci se vÜak zmφnit o n∞kter²ch problΘmech, kterΘ mohou cΘΦka°e potkat, kdy₧ se do Javy pustφ. Nebudu se pokouÜet o hodnocenφ Javy; ₧e jde o dobr² a u₧iteΦn² jazyk, se u₧ prokßzalo v praxi. Nßsledujφcφ povφdßnφ proto berte spφÜe jako hrst dojm∙, kterΘ mΘ seznamovßnφ s nφ doprovßzely.
Jak znßmo, Java je dφtkem firmy Sun Microsystems. Jednφm z hlavnφch cφl∙ tv∙rc∙ tohoto jazyka byla co nejvyÜÜφ nezßvislost na platform∞, a tedy maximßlnφ mo₧nß p°enositelnost. SvΘ mety dosßhli tφm, ₧e vytvo°ili interpretovan² jazyk. Zdrojov² program v Jav∞ se ovÜem neinterpretuje p°φmo. Nejprve se p°elo₧φ do tzv. bajtovΘho k≤du (bytecode, soubory s p°φponou class). Bajtov² k≤d pak interpretuje tzv. javsk² virtußlnφ stroj (Java Virtual Machine, JVM); je asi jasnΘ, ₧e toto °eÜenφ je na ·kor rychlosti. Firma Sun Microsystems sice slibuje vytvo°it procesor, kter² by um∞l bajtov² k≤d provßd∞t p°φmo, ale ten zatφm, pokud vφm, na trhu nenφ.
Program v Jav∞ je, alespo≥ na prvnφ pohled, velice podobn² programu v C++. Ostatn∞ auto°i Javy se tφm, ₧e je Jazyk C++ inspiroval, nikdy netajili; Φasto se dokonce setkßme s tvrzenφm, ₧e Java je C++ po vypuÜt∞nφ potencißln∞ nebezpeΦn²ch rys∙.
╚ist∞ objektovß, ale ne tak docela
O Jav∞ se °φkß, ₧e to je Φist∞ objektov² jazyk. Nenφ to ale tak ·pln∞ pravda, nebo¥ Φφsla, znaky a dalÜφ "primitivnφ typy" nejsou objekty. V n∞kter²ch Φist∞ objektov²ch jazycφch se jako objekty chovajφ dokonce i bloky k≤du; ani s tφm se v Jav∞ nesetkßme. TakΘ t°φdy (tedy objektovΘ typy) nejsou objekty, tak₧e zde nenajdeme metat°φdy, jako nap°. ve Smalltalku.
NicmΘn∞ vÜechny t°φdy v Jav∞ jsou Φleny jednΘ d∞dickΘ hierarchie, a pokud v deklaraci n∞jakΘ t°φdy neuvedeme p°edka, stane se jφm automaticky t°φda Object, kterß je zde spoleΦn²m (pra)p°edkem vÜech t°φd. To znamenß, ₧e vÜechny objekty d∞dφ °adu u₧iteΦn²ch vlastnostφ (ale takΘ vlastnostφ, o kterΘ obΦas v∙bec nestojφme), nap°. metodu equals pro porovnßvßnφ, toString pro p°evod na °et∞zec nebo clone pro vytvo°enφ kopie.
Z tΘm∞° ΦistΘ objektovosti plyne, ₧e v Jav∞ nejsou k dispozici "obyΦejnΘ" funkce; vÜe jsou pouze metody. Existuje ovÜem °ada funkcφ, kterΘ si jako metody objektov²ch typ∙ lze p°edstavit jen t∞₧ko û t°eba b∞₧nΘ matematickΘ funkce jako sinus, kosinus atd. NicmΘn∞ v Jav∞ to jsou statickΘ metody t°φdy Math, tak₧e musφme psßt Math.sin(x) apod. Nemohu si pomoci, p°ipadß mi to jako p°ehnan² fundamentalismus, i kdy₧ n∞kdo bude hovo°it spφÜe o d∙slednosti a mo₧nß i o Φistot∞ nebo eleganci. Zßpis libovolnΘho matematickΘho vzorce v Jav∞ se tφm vzdßlφ matematickΘ praxi, a to nutφ programßtora myslet takΘ na to, jak co pφÜe, a nikoli jen na °eÜen² problΘm. Ostatn∞ p°ipadß mi to i proti zßkladnφm idejφm objektovΘho programovßnφ: Je snad matematika (Math) v n∞jakΘm smyslu t°φda objekt∙? Sotva û zde prost∞ dostala p°ednost snaha po objektovosti p°ed zdrav²m rozumem. (Nejd∙le₧it∞jÜφ je stßt v °ad∞, to p°ece znßme ze ₧ivota...)
Ale kdy₧ u₧ d∙slednost, proΦ tedy nejsou t°φdami takΘ ΦφselnΘ typy nebo t°eba bloky k≤du? (Pokud po tom vÜak zatou₧φme, mßme v Jav∞ p°eddefinovanΘ "obalovΘ" t°φdy Double, Integer atd., jejich₧ instance v sob∞ mohou ukr²vat hodnoty primitivnφch typ∙.)
Pozor, neskßkat?
Java neobsahuje klasick² p°φkaz skoku, i kdy₧ slovo goto pat°φ mezi rezervovanß. (To znamenß, ₧e je nesmφme pou₧φt jako identifikßtor, ale p°φkaz goto pou₧φt nem∙₧eme a jin² v²znam toto klφΦovΘ slovo nemß.) To vypadß hezky; p°i podrobn∞jÜφm pohledu ale zjistφme, ₧e goto zde sice chybφ, ale skoky ne. Vedle p°φkaz∙ break a continue v podob∞, v jakΘ je znßme z jazyka C, tu najdeme konstrukci break nßv∞Ütφ;, kterß umo₧≥uje vyskoΦit z n∞kolika do sebe vno°en²ch cykl∙. (Napadß mne starΘ ΦeskΘ p°φslovφ o vlku, kter² se na₧ral, a o koze, kterß z∙stala celß.)
Balφky
Zdrojov² k≤d je v Jav∞ uspo°ßdßn do tzv. balφk∙ (package); to je konstrukce, kterß nemß v C++ p°esnou analogii û nejspφÜe ji lze srovnat s prostorem jmen (namespace). Balφk je vlastn∞ modul, skupina programov²ch soubor∙ (t°φd) tvo°φcφch logick² celek. P°ekladem balφku vznikne skupina soubor∙ s p°φponou class, kterΘ za b∞hu programu naΦφtß a interpretuje JVM (nebo WWW prohlφ₧eΦ, pokud jde o souΦßst appletu). Jeden balφk je obvykle v jednom adresß°i. JmΘno balφku by m∞lo b²t zalo₧eno na internetovΘ adrese organizace, v nφ₧ byl vytvo°en, a v adresß°ovΘ struktu°e poΦφtaΦe, ve kterΘm je ulo₧en, nenφ to ale nezbytnΘ. (To mß v²znam u balφk∙ sdφlen²ch v mnoha aplikacφch v prost°edφ WWW.)
Balφk musφ b²t ulo₧en v adresß°i, kter² odpovφdß jeho jmΘnu. Jsou-li nap°. javskΘ soubory ulo₧eny v adresß°i C:\JAVA\SRC, musφ b²t balφk jmΘnem java.src.b1 ulo₧en v adresß°i C:\JAVA\SRC\B1. Podobn∞ jako adresß°e mohou obsahovat podadresß°e, mohou i balφky obsahovat "podbalφky".
Identifikßtory musφ b²t jednoznaΦnΘ v rßmci balφku. Chceme-li pou₧φt jmΘno z jinΘho balφku, musφme ho kvalifikovat, tj. p°ipojit k n∞mu pomocφ teΦky jmΘno balφku. Pot°ebujeme-li tedy nap°. deklarovat t°φdu Ap1 jako potomka t°φdy Applet, musφme napsat
class Ap1 extends java.awt.Applet
{/* ... */ }
To je nepohodlnΘ, a proto se Φasto pou₧φvß p°φkaz import:
imoport java.awt.*;
class Ap1 extends Applet
{/* ... */ }
Tento p°φkaz b²vß srovnßvßn s direktivou #include, ale to nenφ zcela p°esnΘ, nebo¥ imoport nezp∙sobφ naΦtenφ importovanΘho balφku p°i p°ekladu. Daleko p°esn∞jÜφ je srovnßnφ s p°φkazem using z ISO C++, kter² takΘ umo₧≥uje vynechat kvalifikaci identifikßtorem prostoru jmen.
T°φdy
Deklarace t°φdy v Jav∞ se na prvnφ pohled podobß deklaraci objektovΘho typu v C++. Sice chybφ struktury a unie, n∞kterß klφΦovß slova se liÜφ a definice metod musφme zapsat celΘ do t∞la t°φdy, za deklaracφ nepφÜeme st°ednφk, ale to tolik nevadφ. OvÜem jsou tu rozdφly, na kterΘ je t°eba pamatovat. O prvnφm z nich jsme u₧ mluvili: V Jav∞ jsou vÜechny objekty navzßjem p°φbuznΘ. Pokud v deklaraci neuvedeme p°edka, pou₧ije se automaticky t°φda Object, kterß je spoleΦn²m p°edkem vÜech objekt∙ v Jav∞.
Jin²m p°ekvapenφm je automatickß pozdnφ vazba (polymorfismus). Z C++ jsem byl zvykl², ₧e pokud po₧aduji pro n∞kterou metodu pozdnφ vazbu, musφm si o to °φci, tj. musφm ji deklarovat jako virtußlnφ. V Jav∞ se pozdnφ vazba uplat≥uje automaticky, m∙₧eme ji ale naopak potlaΦit tφm, ₧e pomocφ klφΦovΘho slova super p°edepφÜeme volßnφ metody p°edka. (AutomatickΘ pou₧itφ pozdnφ vazby je v Φist∞ objektov²ch jazycφch obvyklΘ, vede to ale k ni₧Üφ efektivit∞. OvÜem oproti skuteΦnosti, ₧e Java je interpretovßna, je to zpravidla naprosto zanedbatelnΘ.)
DalÜφm rozdφlem je absence vφcenßsobnΘ d∞diΦnosti. Ono jφ ve skuteΦnosti nejspφÜ nenφ v∙bec t°eba, ale je to pohodln² nßstroj, kter² umo₧≥uje programßtor∙m snßze °eÜit n∞kterΘ slo₧it∞jÜφ situace p°i sklßdßnφ objekt∙. (Kdy₧ u₧ jsme u toho û ona vlastn∞ nenφ nutnß ani d∞diΦnost. A kdy₧ p∙jdeme v podobn²ch ·vahßch dßl, zjistφme, ₧e nenφ nezbytnΘ objektovΘ programovßnφ, a dokonce se lze obejφt i bez vyÜÜφch programovacφch jazyk∙. Koneckonc∙, vÜe, co lze naprogramovat, lze napsat p°φmo ve strojnφm k≤du...) Oficißlnφ p°φruΦky nßs ovÜem pouΦφ, ₧e vφcenßsobnß d∞diΦnost je pln∞ nahrazena mechanismem rozhranφ (interface).
ZajφmavΘ takΘ je, ₧e d∞d∞nφ lze v Jav∞ omezit. Jestli₧e v deklaraci t°φdy pou₧ijeme modifikßtor final, nebude mo₧nΘ od nφ odvodit potomka. Podobn∞ lze pomocφ tohoto modifikßtoru zakßzat p°edefinovßnφ jednotliv²ch metod v potomkovi.
P°φstupovß prßva
P°φstupovß prßva, tedy nßstroje pro omezovßnφ neautorizovanΘho p°φstupu ke slo₧kßm objekt∙, vypadajφ v Jav∞ na prvnφ pohled velice podobn∞ jako v C++. Najdeme tu klφΦovß slova public, protected a private a takΘ vysv∞tlenφ jejich v²znamu nßm bude znφt pov∞dom∞; skuteΦnost, ₧e tyto specifikßtory zapisujeme p°ed ka₧dou datovou slo₧ku nebo metodu, nßs jist∞ z mφry nevyvede.
NicmΘn∞ brzy zjistφme, ₧e zde je n∞kolik v²znamn²ch rozdφl∙. Asi nejd∙le₧it∞jÜφm z nich je fakt, ₧e se p°φstupovß prßva uplat≥ujφ nejen na ·rovni t°φdy, ale na ·rovni balφku. Slo₧ky deklarovanΘ jako chrßn∞nΘ (protected) jsou p°φstupnΘ nejen v metodßch danΘ t°φdy a jejφch potomk∙, ale v celΘm balφku.
P°itom ve skuteΦnosti existujφ Φty°i ·rovn∞ p°φstupov²ch prßv; Φtvrtou je implicitnφ hodnota (kdy₧ nepou₧ijeme ₧ßdn² specifikßtor). Implicitnφ p°φstupovß prßva jsou sv²m rozsahem n∞kde mezi hodnotami private a protected.
Navφc p°i d∞d∞nφ nelze p°φstupovß prßva omezit, jen rozÜφ°it. To znamenß, ₧e deklarujeme-li nap°. v p°edkovi ve°ejn∞ p°φstupnou metodu, nelze ji v potomkovi p°ekr²t chrßn∞nou nebo soukromou metodou.
Trochu nezvyklΘ takΘ je, ₧e ka₧d² soubor m∙₧e obsahovat nejv²Üe jednu ve°ejn∞ p°φstupnou t°φdu a ta musφ b²t ulo₧ena v souboru, kter² se jmenuje stejn∞ jako tato t°φda. Trochu to p°ipomφnß n∞kterß podivnß omezenφ z Pascalu, mß to ale svoji logiku û interpreter Javy vyhledßvß p°elo₧enΘ t°φdy prßv∞ podle jmen soubor∙.
Rozhranφ
Rozhranφ je vlastn∞ jak²si seznam metod. V C++ by asi nejbli₧Üφm ekvivalentem byla struktura obsahujφcφ pouze Φist∞ virtußlnφ metody (a p°φpadn∞ konstanty). T°φda smφ mφt jen jednoho p°edka, vedle toho ale m∙₧e implementovat libovoln² poΦet rozhranφ. (Rozhranφ se ned∞dφ, ale implementujφ; to m∙₧e vypadat na prvnφ pohled jako slovφΦka°enφ, nicmΘn∞ Java pro to pou₧φvß jinΘ klφΦovΘ slovo.)
T°φda, kterß implementuje urΦitΘ rozhranφ, se zavazuje implementovat jeho metody. JmΘno rozhranφ pak m∙₧eme podobn∞ jako jmΘno t°φdy pou₧φt k definici reference na objekt. (Nelze ho vÜak samoz°ejm∞ pou₧φt p°i vytvß°enφ instance pomocφ operßtoru new û viz dßle.)
Java a ΦeÜtina
SvΘrßznou kapitolou v ka₧dΘm programovacφm nßstroji je jeho pom∞r k nßrodnφm prost°edφm. I kdy₧ obΦas narß₧φm na p°edstavu, ₧e vÜechny programy by se m∞ly chovat jednotn∞, tedy hovo°it anglicky (nejlΘpe s americk²m p°φzvukem), praxe velk²ch softwarov²ch firem je jinß a prost°edφ, kterΘ se s ΦeÜtinou nedokß₧e snadno a dob°e vyrovnat, je u nßs Üpatn∞ prodejnΘ. (Ostatn∞ v mnoha sousednφch zemφch je vytvß°enφ program∙ nepodporujφcφch nßrodnφ jazyk v podstat∞ nemyslitelnΘ a lokalizace zahraniΦnφch program∙ je morßlnφ, nebo dokonce i zßkonnou povinnostφ; to poslednφ platφ nap°. ve Francii, ale i v N∞mecku je lokalizace v²vojov²ch nßstroj∙ obvyklß.)
Prvnφm a nejd∙le₧it∞jÜφm momentem je v tomto ohledu mo₧nost pou₧φvat nßrodnφ abecedu. Vzhledem k po₧adavku maximßlnφ p°enositelnosti se tv∙rci Javy rozhodli ponechat °eÜenφ tohoto problΘmu na konkrΘtnφch implementacφch. To znamenß, ₧e v Jav∞ pracujeme pouze s n∞kolika "abstraktnφmi" fonty, kterΘ se jmenujφ Serif, Monospaced atd., a jejich p°i°azenφ "konkrΘtnφm" font∙m je popsßno v souborech s nßzvy font.properties.xx, kde xx je p°φpona oznaΦujφcφ nßrodnφ prost°edφ a p°φpadn∞ i platformu. Soubor s nßzvem font.properties (bez p°φpony) popisuje implicitnφ p°i°azenφ, kterΘ odpovφdß americkΘ angliΦtin∞.
V JDK 1.1, dodßvanΘm nap°. v JBuilderu 2, bylo k dispozici znaΦnΘ mno₧stvφ (cca 30) t∞chto soubor∙ pro nejr∙zn∞jÜφ jazyky, mezi nimi i pro ΦeÜtinu a slovenÜtinu (s p°φponami cs, resp. sk), polÜtinu, ruÜtinu, srbochorvatÜtinu, ma∩arÜtinu atd.
V JDK 1.2 jich je jen dev∞t, z toho t°i pro ΦφnÜtinu; dßle tu najdeme korejÜtinu, hebrejÜtinu, arabÜtinu a thajÜtinu, z evropsk²ch jazyk∙ pouze ruÜtinu. P°itom soubor font.properties.cs, p°enesen² z p°edchozφ verze pod Windows 95, nefunguje. (Pou₧ijete-li font.properties.cs z p°edchozφ verze pod Windows NT, p°ekladaΦ vßm oznßmφ, ₧e nem∙₧e najφt pot°ebnΘ fonty, ale ΦeÜtina bude fungovat.) Autory jazyka û Φi spφÜe jejich obchodnφ mana₧ery û z°ejm∞ v²vojß°i v mal²ch evropsk²ch zemφch prost∞ nezajφmajφ; Φlov∞ku se na jazyk derou oÜklivΘ poznßmky o aroganci moci, tj. monopolu, a podobn∞. (Nebo nßs takΘ m∙₧e napadnout, ₧e to prost∞ nezvlßdli; je otßzka, co je horÜφ.)
Poznamenejme vÜak, ₧e v souΦasnΘ dob∞ je ji₧ k dispozici ΦßsteΦnΘ °eÜenφ, kterΘ umo₧≥uje pou₧φvat ΦeÜtinu alespo≥ v n∞kter²ch komponentßch a v jednom jedinΘm pφsmu. OvÜem toto °eÜenφ nepochßzφ, pokud vφm, od tv∙rc∙ Javy.
P°φÜt∞
V²Φet p°ekvapenφ, kterß mohou potkat cΘΦka°e, kdy₧ si zaΦne s Javou, tφm samoz°ejm∞ nekonΦφ. V p°φÜtφm Φφsle se proto k Jav∞ vrßtφme jeÜt∞ jednou.