autor: Ivan Kupka

Verzia 1

home uvod K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14

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“.

 

Pokus s balíkmi

  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.

 

 

Kód P9.1

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;

          }

}

Kód P9.2

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>

 

Mená tried z balíkov

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

.

 

Classpath

Zatiaľ sme si ukázali jednu možnosť práce s balíkmi. A to spúšťanie z materského adresára, obsahujúceho podadresáre s názvami a triedami balíkov. Pokročilejšia cesta  spočíva v nastavení systémovej premennej CLASSPATH (tá môže ukazovať nielen cestu k balíkom, ale aj k súborom typu .jar a .zip. O tom tu hovoriť nebudeme). Zvolíme si adresár, v ktorom budú všetky balíky. Nech je to napríklad adresár (v OS Windows) D:\javaprogramy\balicky. Systémovú premennú CLASSPATH nastavíme na hodnotu D:\javaprogramy\balicky ,respektíve, čo je lepšie, na hodnotu .;D:\javaprogramy\balicky . Prvá cesta, označená len bodkou hovorí, že súbory typu „class“ možno nájsť aj v práve používanom adresári. Do CLASSPATH možno pridať aj ďalšie cesty, jednotlivé položky sa oddeľujú bodkočiarkou:

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

 

Uloženie balíkov v adresároch

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.

 

Hierarchia balíkov, adresáre

  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“.

 

Prístupové práva

  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

 

  Vytvorte balík  „javo.io“ s triedou File poprípade s inými triedami a s príslušnými metódami

(č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

home uvod K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14

Vaše komentáre: kupka@fmph.uniba.sk