Java 9
Balíky
Cieľom textu je oboznámiť sa s vytváraním balíkov a,
ich používaním. Import balíkov,CLASSPATH, prístupové práva.
Na balíček
alebo balík v Jave sa môžeme dívať ako na knižnicu. Všetky objekty vytvorené v jazyku
Java spoločnosťou Sun sú súčasťou knižnice-balíka java. Táto má svoje
„podknižnice“, napríklad knižnicu java.lang, ktorá sa načítava automaticky počas
prekladania a počas behu každého
javovského programu. Tento balík obsahuje napríklad triedu System. Pomocou statického člena-objektu „out“ tejto
triedy sme schopní tlačiť na konzolu.
Ak potrebujeme v programe niektoré objekty týkajúce sa vstupov
a výstupov (napr. FileReader, alebo
ObjectOutputStream), stačí nám importovať knižnicu java.io pomocou kľúčového slova „import“:
import java.io.*;
V Jave môžeme ľahko vytvárať svoje vlastné balíčky. Každý by
mal združovať triedy, ktoré slúžia – z určitého pohľadu – spoločnému
účelu. Povedzme napríklad, že by sme začali vytvárať súbor tried, slúžiacich na
podporu chatterbotu –„pokecníka“. Po menšej úprave by nám mohli poslúžiť triedy
Besednik a Pokec , známe
z kódu P8.4. O chvíľu ich upravíme a umiestnime do spoločného
balíka, nazvaného rozhovor. Ako
pomocná trieda nám poslúži trieda Vstup, tú dáme do balíka citanie,
pretože jej použitie je univerzálne a bolo by škoda vnímať ju iba
v kontexte „rozhovor“.
Vytvorte
z nasledujúcich kódov súbory Besednik.java, Pokec.java a
Vstup.java . Vytvorte adresár napriklad «matersky », z ktorého budete
programy prekladať a spúštať. V tomto adresári vytvorte dva
podaresáre : « rozhovor » a « citanie ». Do
adresára « rozhovor » uložte súbory Besednik.java a Pokec.java. Súbor
Vstup.java uložte do adresára « citanie ».
Vojdite o úroveň vyššie,
do adresára « matersky». Z neho postupne preložte všetky súbory. Napr.
Vstup.java preložíme v DOSe príkazom :
javac citanie/Vstup.java
Nakoniec
spustite program Pokec príkazom:
java rozhovor.Pokec
( P.S.
Zrejme budete musieť definíciu poľa
v Pokec.java začínajúcu v riadku
„ String[] vety = new String[]...“ znovu naeditovať
ako jeden riadok.).
Nasledujú
jednotlivé kódy tried, ktoré poznáme už minulých kapitol. Tu sú mierne
upravené. Väčšie zmeny sú len v triede „Pokec“, v ktorej je
doplnených niekoľko metód, určených na besedovanie s užívateľom
prostredníctvom klávesnice a terminálu. Principiálna zmena prirodzene je
tá, že triedy teraz patria do konkrétnych balíkov.
package rozhovor;
import java.io.*;
class Besednik
implements Serializable{
int
vek = -1;
String
meno = "?";
Boolean
jeMuz = null;
public
void setVek(int j ){
vek
= j;
}
public
Besednik(int vek, String meno, boolean jeMuz){
this.vek = vek;
this.meno = meno;
this.jeMuz = new Boolean(jeMuz);
}
//
nasledujuci konstruktor sluzi pre
spolupracu
// s
metodou nacitaj() v triede Pokec
public
Besednik(){
this.meno
= "Nacitanie prebehlo zle, neviem
urcit udaje o Besednikovi";
}
public
void setMeno(String name){
meno
= name;
}
public
String getMeno(){
return
meno;
}
public
void setPohlavie(String s){
if(s.equals("ano"))
jeMuz = new Boolean(true);
else
{
if(s.equals("nie"))
jeMuz = new Boolean(false);
else
System.err.println("Z tohto udaju neviem urcit pohlavie.");
}//EOVonkajsieElse
}//EOMethod
public
String toString(){
String s = meno;
if(jeMuz
!= null){
boolean
muz = jeMuz.booleanValue();
if(muz)
{
s
+= " je muz ";
}
else
{
s+=
" je zena ";
}
}
if(vek
!= -1){
s+=
" vo veku " + String.valueOf(vek)
+ " rokov";
}
s+=".";
return
s;
}
}
package rozhovor;
import citanie.*;
import java.io.*;
public class Pokec {
// vety, ktore sa pouziju nahodne pri besede
String[] vety = new
String[]{"Aha.","Zaujimave.","S tym nemozem
suhlasit.","Este sa nad tym zamyslim.","Ked to vravis ty...","Vies,ja
vlastne nicomu nerozumiem.","Presne! To je vystizne.","No
dobre, ked inak nedas.","Moment...musim sa vysmrkat.","Ze
by mi to davalo zmysel...", "Povedz mi o tom viac.","Zrejme
mas pravdu.","Radsej zmenme temu.","Kto by to
povedal?","Mozno o tom nevies, ale som expert na
dazdovky",":-)","Vies, aku je rozdiel medzi hadom a
dazdovkou?","Dazdovky si rozdiel medzi hadom a dazdovkou neuvedomuju,
hady ano."};
// aby v metode "nahodnePovedz"
nepovedal odpoved o //dazdovkach ako prvu
int poslednyIndex = vety.length -1;
public
void rozhovor(Besednik bes){
System.out.println("Napis prosim tvoje
meno a stisni enter.");
bes.setMeno( Vstup.citaj());
System.out.println("Napis prosim svoj
vek. Cislom.");
int kolkoRokov = Integer.parseInt(Vstup.citaj());
bes.setVek(kolkoRokov);
System.out.println("Si muz? Odpovedz
prosim \"ano\" alebo \"nie\".");
bes.setPohlavie(Vstup.citaj());
}
//
nova metoda, vzdy nacita hlasku besednika a potom nahodne odpovie
public
void beseduj(){
System.out.println("Napis
nieco a stisni enter. Rozhovor ukoncis napisanim \"exit\"");
while(true){
String s = Vstup.citaj();
if(s.equals("exit")) return;
nahodnePovedz();
}
}
//
metoda generujuca nahodnu odpoved
//
poslednyIndex sluzi na to, aby sa 2x za sebou neopakovala odpoved
//
plus obstara "inteligentnu" reakciu o dazdovkach
public
void nahodnePovedz(){
int
dlzka = vety.length;
int
dazdovkyOtazka = vety.length -2;
int
dazdovkyOdpoved = vety.length-1;
//
osetruje tie dazdovky
if(poslednyIndex ==( vety.length -2)){
poslednyIndex
=vety.length-1;
}
else{
//
vylosuj nahodny index vety a povedz ju
//
zapamataj si predosly index
// zabran opakovaniu tej istej vety
int index = (int)(Math.random()*(vety.length));
if (poslednyIndex == index){
if (index==0){
poslednyIndex=1;
}
else{
poslednyIndex = index -1;
}
}//EOIf
else{
poslednyIndex = index;
}
}//EOElse
System.out.println(vety[poslednyIndex]);
}
//
tato metoda vrati objekt Besednik po precitani suboru
public Besednik nacitaj(File f){
Besednik vzkrieseny = new Besednik();
try{
FileInputStream
in = new FileInputStream(f);
ObjectInputStream
vzkriesObjekt = new ObjectInputStream(in);
//
moze sposobit ClassNotFoundException:
vzkrieseny
= (Besednik)vzkriesObjekt.readObject();
}
catch(IOException e){
System.err.println("Problemy
pri krieseni ulozeneho Besednika.");
}
catch(ClassNotFoundException cnf){
System.err.println("Zial,
Besednici uz neexistuju.");
}
return
vzkrieseny;
}
public void uloz(Besednik bes){
File
cakaren = new File("cakaren.bin");
try{
if(! (cakaren.exists() &&
cakaren.isFile()) ){
cakaren.createNewFile();
}
FileOutputStream
out = new FileOutputStream(cakaren);
ObjectOutputStream
zapisObjekt = new ObjectOutputStream(out);
zapisObjekt.writeObject(bes);
out.close();
}//EOTry
catch(IOException
e){
System.err.println("Chyba pri ukladani
Besednika");
}
}//EndOfUloz
public
static void main(String[] args){
Pokec skladnik = new Pokec();
Besednik prvyClovek = new
Besednik(0,"Adam",true);
// ak uz udaje o osobe existuju, nacitaj ich
zo suboru cakaren.bin
File cakaren = new
File("cakaren.bin");
if(cakaren.exists() &&
cakaren.isFile()){
prvyClovek = skladnik.nacitaj(cakaren);
System.out.println("Ahoj "
+prvyClovek.getMeno() +".");
// zacne besedu
skladnik.beseduj();
}
// ak nie, prvyClovek ostava az do rozhovoru
nezmeneny
//
Nacita udaje z klavesnice a nastavi nove hodnoty do objektu Besednik
else{
skladnik.rozhovor(prvyClovek);
System.out.println(prvyClovek + "\n
Ukladam Besednika pre dalsi beh programu.");
skladnik.uloz(prvyClovek);
//
zacne besedu
skladnik.beseduj();
}
// objekt Besednik ulozi do suboru
cakaren.bin
}
}
Kód P9.3
package
citanie;
import java.io.*;
public
class Vstup{
public static String citaj(){
String
nacitane = "zatialNenacitane";
try{
byte[]
riadok = new byte[30];
System.in.read(riadok);
nacitane
= new String(riadok).trim();
return
nacitane;
}
catch(IOException
e){
System.out.println("Chyba
v nacitani!");
return
nacitane;
}
}
public
static void main(String[] args){
System.out.println("Napis
podstatne meno vzoru dub a daj enter:");
String
podstMeno = Vstup.citaj();
System.out.println("Siesty
pad slova " +
podstMeno + " je:
" + podstMeno + "e");
}
}
Príklad ladenia s spustenia programu – materský
adresar sa tu volá „ baliky“, má dva podadresáre: „citanie“ a „rozhovor“ aj
spríslušnými súbormi tried:
D:\Ivan\fakulta\vyuc Javy>cd baliky
D:\Ivan\fakulta\vyuc Javy\baliky>javac
citanie/Vstup.java
D:\Ivan\fakulta\vyuc Javy\baliky>javac rozhovor/Besednik.java
D:\Ivan\fakulta\vyuc Javy\baliky>javac
rozhovor/Pokec.java
D:\Ivan\fakulta\vyuc Javy\baliky>java
rozhovor.Pokec
Napis prosim tvoje meno a stisni enter.
...
(atd –prebieha beseda)
....
exit
D:\Ivan\fakulta\vyuc Javy\baliky>
Všimnime si, že zvonku je trieda „Pokec.class“ teraz
vnímaná ako trieda s menom
„rozhovor.Pokec.class“. To preto, lebo patrí do balíka „rozhovor“. Mohli by sme
napríklad vytvoriť aj balík s názvom „politika“ a v ňom
implementovať úplne inú triedu „Pokec“. Táto by bola v rámci balíka
„politika“ dosiahnuteľná cez menom „Pokec“, zvonku balíka cez meno
„politika.Pokec“.
Prístup ku triedam balíka
Kód P9.4
import rozhovor.*;
public class VolanieZvonkuBalika {
public static void main(String[] args){
Pokec.main(args);
//Besednik
skryty = new Besednik();
}
}
po
preložení spustí metódu „main()“ triedy rozhovor.Pokec. Táto trieda je
prístupná aj zvonka balíka rozhovor, lebo je označená ako verejná.
Trieda rozhovor.Besedník nemala žiadne označenie. Odkomentujme riadok
//Besednik skryty = new Besednik();
a spustime prekladač:
D:\Ivan\fakulta\vyuc Javy\baliky>javac
VolanieZvonkuBalika.java
VolanieZBalika.java:7: rozhovor.Besednik is not
public in rozhovor; cannot be accessed from outside package
Besednik
skryty = new Besednik();
...
Prekladač
nám dá jasne najavo, že zvonku balíka nemáme ku triede Besednik
prístupové právo. Tak sme to aj chceli, táto trieda slúžila ako pomocná pri
práci vo verejnej tried Pokec. Ak budeme chcieť náš chatterbot rozšíriť,
možno sa v určitej fáze úplne vzdáme myšlienky „Besedníka“, alebo ho
naopak rozvinieme o nové aspekty. Avšak používateľ triedy Pokec si
s tým nebude musieť robiť starosti. Stále bude pracovať len s triedou
Pokec a jej jedinou verejnou metódou
main() . (Bežne takéto definovanie
a volanie metód nie je zaužívané. Tu slúži na ilustráciu toho, ktoré triedy a metódy sú prístupné
zvonku balíka a ktoré nie.)
.
cesta1;cesta2;……;poslednaCesta
Presný
význam premennej Classpath sa z času na čas mení, väčšinou po zavedení
novej verzie jazyka Java.
K aktuálnemu stavu sa dá dopátrať na
stránke www.java.sun.com .
(Príklad nastavovania CLASSPATH vo Windows 2000:
Start,
Setttings, Control Panel, System,
Advanced, Environment Variables, New( neskôr pri zmenách „Edit“ ))
Ak sme CLASSPATH nastavili napríklad na hodnotu D:\javaprogramy\balicky
tak všetky preložené súbory s príponou „class“,
patriace triedam z balíka
„rozhovor“ musia ležať v adresári „rozhovor“, ktorý je umiestnený
v adresári D:\javaprogramy\balicky.
Aby sa
zabránilo kolízii mien v rámci celého sveta, pre balíky sa odporúča voliť
ich názvy vychádzajúc z mena domény na internete. Napríklad balík
„rozhovor“ umiestnený na matematicko-fyzikálnej fakulte Univerzity Komenského e v Bratislave by sa mal
radšej volať sk.uniba.fmph.uzivatel.rozhovor
A cesta knemu by vyzerala takto:
root\sk\uniba\fmph\uzivatel\rozhovor
kde root by bola cesta k adresáru, v ktorom ležia balíky.
Tento spôsob sa málokedy používa, je ale dobré
zapamätať si, že meno balíka môže mať
tvar slovo1.slovo2.slovo3 a príslušné triedy balíka ležia
v adresári slovo3, ktorý leží v adresári slovo2 atď.
Koniec
koncov, takúto štruktúru mien vidíme aj v pôvodných balíkoch javy.
Napríklad aj v príkaze:
Import java.util.*;
kde plné meno balíka
je „java.util“.
Pri
deklarácii premenných a metód v jazyku Java používame špecifikátory
prístupu. Sú to kľúčové slová private , protected , public.
Ak nepoužijeme žiadne z týchto slov, ide implicitné označenie
prístupu. Poradie, v ktorom sa
prístupnosť metód a premenných zväčšuje je toto: Najmenej prístupné sú
prvky označené slovom private, prístupnejšie sú implicitne označené
prvky, ešte viditelnejšie sú
chránené, označené slovom protected a prvky označené ako public sú
viditeľné všade. Ešte raz, presnejšie (Podľa Schildta):
private - viditeľnosť len vnútri
materskej triedy
implicitne označený prístup - pridá sa aj viditeľnosť vnútri toho istého balíka, okrem
podtried
protected – viditeľná
v každej triede balíka, teda aj v podtriedach
public – viditeľné ešte aj vnútri rôznych balíkov, okrem
podtried.
Cvičenia
Cv9.1
Vykonajte „pokus s balíkmi“ opísaný v texte
vyššie.
Cv9.2
(čo najjednoduchšie implementovanými), tak, aby sa
kód P8.1 preložil a zbehol, keď v ňom riadok „import java.io.*;” zameníte za riadok „import
javo.io.*;”.
Cv9.3
Experimentujte s označeniami prístupu pri triedach Besednik a Pokec, meňte prístupové práva k jednotlivým premenným a metódam a sledujte, nakoľko sú z vnútra, alebo zvonka balíka prístupné.
Cv9.Nepovinné
Otestovať nasledujúcu možnosť: Keď je
v CLASSPATH nastavených viac ciest, rôzne triedy z jedného balíka
môžu byť umiestnené v rôznych adresároch.
An interesting consequence of the package
specification mechanism is that files which are part of the same package may
actually exist in different directories. The package name will be the same for
each class, but the path to each file may start from a different directory in
the class path.
© Ivan Kupka
Vaše komentáre:
kupka@fmph.uniba.sk