Java 3
Polia, metódy, konštruktory
Cieľom
tejto časti je oboznámiť sa
podrobnejšie s poľam a s definovaním metód v Jave.Ďalšie
témy:Prvá informácia o premenných inštancie a o konštruktore. Vytváranie
náhodných čísel.
Polia po druhý raz
Na pole sa môžeme dívať ako na kontajner,
ktorý má presne určený počet prvkov a ich typ. Pole uskladňuje vždy len
prvky jednej triedy. Rozmer poľa
nám vráti
premenná length, pole mojePole má dĺžku
int dlzka
= mojePole.length ;
Pole môže mať viac rozmerov, nemusí byť však
„pravidelné“. T. j. napríklad v prípade dvojrozmerného poľa všetky jeho
„riadky“, či „stĺpce“ nemusia byť rovnako dlhé. Pozrime si nasledovné
trojrozmerné pole typu String[][][],
ktoré v sebe uchováva informáciu o prezývkach chlapcov,
chodiacich do posilovne. Orientáciu sťažuje, že sú medzi nimi dvaja Petrovia Novákovia. Jozefov a Karolov je tu tiež
viac. Spolu chodí do posilovne 9 chlapcov. Ich prezývky znázorňuje
nasledujúca tabuľka:
Mena Priezviska: |
Novák |
Kováč |
Peter |
Petko, Pato |
- |
Jozef |
Jozino, Jojo, Pepo |
Prcek |
Karol |
Kajo |
Kladivo, Oheň |
Definíciu
poľa a tlačenie niektorých prezývok uvidíme v nasledujúcom kóde.
Pozor! Keď budete definovať viacrozmerné polia, musíte mať najprv
definované menšie rozmery, indexy, kým začnete definovať tie väčšie, či dokonca
priraďovať indexom konkrétne hodnoty.
Kód P3.1
public
class JozefoviKamosi {
public static void main(String[] args){
/*
Prva suradnica nasledujuceho pola vyjadruje
meno:
0. Peter
1. Jozef
2. Karol
Druha suradnica priezvisko
0. Novak
1. Kovac
napriklad prvok [1][1] obsahuje prezyvky
vsetkych Jozefov Kovacov,
je
to jednorozmerne pole stringov
*/
// vytvaram polozky pre mena
String[][][] prezyvky = new String[3][][];
// meno Peter ma len jedno priezvisko, s
dvomi prezyvkami
prezyvky[0] = new String[1][2];
// zapiseme tie prezyvky
prezyvky[0][0][0] = "Petko";
prezyvky[0][0][1] = "Pato";
// meno Jozef ma dve priezviska
prezyvky[1] = new String[2][];
//u
Jozefov zaplnime priezvisko
Novak prezyvkami
prezyvky[1][0] = new
String[]{"Jozino","Jojo","Pepo"};
// teraz Jozefi a priezvisko Kovac
//prezyvky[1][1][0] = "Prcek";
/* toto sice prekladac bez problemov prelozi
ale
program za behu zhavaruje a zahlasi
"java.lang.NullPointerException"
chyba bola v tom, ze musime najprv urcit,
ake velke bude pole prezyvky[1][1]
este sme to nedeklarovali:
*/
prezyvky[1][1] = new String[1];
prezyvky[1][1][0] = "Prcek";
// teraz Karolovia, najprv polia
priezvisk
prezyvky[2] = new String[2][];
//
teraz dlzky poli prezyvok v jednotlivych priezviskach
prezyvky[2][0] = new String[1];
prezyvky[2][1] = new String[2];
//prezyvka Karola Novaka:
prezyvky[2][0][0] ="Kajo";
//prezyvky Karolov Kovacov
prezyvky[2][1][0] = "Kladivo";
prezyvky[2][1][1] = "Ohen";
System.out.println("Tlacim prezyvky
Jozefov:");
for(int indexPriezviska = 0; indexPriezviska
< prezyvky[1].length;
indexPriezviska++){
for(int indexPrezyvky = 0;
indexPrezyvky < prezyvky[1][indexPriezviska].length; indexPrezyvky++){
System.out.print( prezyvky[1][indexPriezviska][indexPrezyvky] + " " );
}//EOmalyFor
}//EOvelkyFor
System.out.println();
}//EndOFmain
}//EndOfClass
Metódy
Základom každej triedy sú jej premenné a metódy. Vo všeobecnosti by
každá metóda mala realizovať iba jednu úlohu. Každá metóda má samozrejme meno,
podľa ktoré ho ju v programe voláme – spustíme.
Metódu musí zavolať objekt tej
triedy, v ktorej je metóda definovaná. A to takto: nazovObjektu.nazovMetody(parametre); . (Až na statické metódy,
ktoré stačí volať menom triedy: MenoTriedy.nazovMetody(parametre); )
Metóde môžeme dať akékoľvek meno
okrem – kľúčových slov jazyka Java . (Bolo by dosť hlúpe pomenovávať metódy slovami
ako if, double. while private).
Takisto názov „main()“ si rezervujme pre metódu, ktorou začína náš
program.
V nasledujúcom príklade si
všimnite rozdiel medzi používaním
statickej metódy - tzv. metódy triedy - "pis" a metódy instancie "tlac".
Preštudujte aj správanie sa podobnej metódy "tisk", ktorá má
návratovy typ "String".
public class Pisanie {
public
static void pis(String s) {
System.out.println(s);
}
public
void tlac(String s){
System.out.println(s);
}
public
String tisk(String s){
System.out.println(s);
int i = s.length();
//zapise do Stringu aky dlhy text
tlaci
String vystup = "Metoda
\"tisk\" vytlacila text s " +(new Integer(i)).toString() +" znakmi.";
return vystup;
}
public
static void main(String[] args){
String pozdrav = "ta zdravi.";
Pisanie.pis("Pisanie.println
" + pozdrav);
//Pisanie.tlac("Pisanie.tlac
" + pozdrav);
//non-static method tlac(java.lang.String) cannot be referenced
from a
// static context
Pisanie pisar = new Pisanie();
pisar.tlac("pisar.tlac " + pozdrav);
pisar.pis("pisar.pis " + pozdrav);
String coVytlacilTisk = pisar.tisk("pisar.tisk " +
pozdrav);
System.out.println(coVytlacilTisk);
}//endOfMain
}//endOfPisanie
/* Vystup:
Pisanie.println
ta zdravi.
pisar.tlac ta zdravi.
pisar.pis ta zdravi.
pisar.tisk ta zdravi.
Metoda "tisk" vytlacila
text s 21 znakmi.
Všeobecný tvar metódy
Všeobecný tvar metódy vyzerá takto:
typMetody navratovyTyp
menoMetody(zoznamParametrov){
//telo
metody
}
typMetody netreba nutne použiť, ak sa v opise metódy
nachádza, ide o informáciu, či je metóda prístupná aj zvonku triedy,
poprípade alebo či je statická (napr: „public
static“ alebo „private“ ).
navratovyTyp
je označenie typu premennej, alebo dátového typu, ktorý metóda vracia.
Napr: String alebo double .
menoMetody
je meno, ktoré sme pre metódu
zvolili. Malo by byť, pokiaľ je to možné, výstižné.
ZoznamParametrov
vymenováva typy jedonotlivých parametrov, s akými metóda pracuje.
Je napísaný v tvare zoznamu, kde každá položka je dvojica typ
a identifikátor. Položky oddeľujeme čiarkou. Napríklad:
public void napisNiekolkoKrat(String totoNapis, int tolkotokratToNapis) {
for(int i
= 1; i <= tolkotokratToNapis; i++) System.out.println(totoNapis);
}
Keď metóda nevracia žiadnu hodnotu, jej typ musíme
označiť slovom void. Ostatne, ak by sme zabudli, prekladač nás na túto
povinnosť upozorní. Kód:
public
napisNiekolkoKrat(String totoNapis, int tolkotokratToNapis) {
for(int i
= 1; i <= tolkotokratToNapis; i++) System.out.println(totoNapis);
}
má za
následok hlásenie:
invalid method declaration; return type required
public
napisNiekolkoKrat(String totoNapis, int tolkotokratToNapis) {
^
1 error
Príkaz return
Príkaz return
ukončuje metódu. Ak je metóda typu void, ukončí svoju prácu najneskôr vtedy,
keď narazí na poslednú pravú zátvorku. Ak sa však pred zátvorkou v priebehu
vykonávania metódy vyskytne príkaz “return;” metóda
ukončí svoju činnosť.
Metódy,
ktoré deklarujú, že vracajú hodnotu, musia tak počas svojho behu urobiť. T. j.
metóda typu
long
velkostPremii(boolean
jeToKamarat?){
musí (v
každej svojej možnej vetve) nakoniec vrátiť premennú typu long. Napríklad
takto:
long
premie = 0;
if(jeToKamarat?) {
premie = 1000000;
}
return
premie;
Metóda
je jednoznačne určená svojim názvom a zoznamom argumentov
Kód P3.3
public
class Metody {
public String dajInfo(String s){
System.out.println("\""
+ s + "\" zacina na pismeno " + s.substring(0,1));
return "skumal som retazec " +
s;
}
/*
public int dajInfo(String s){
int
dlzkaStringu = s.length();
System.out.println("Dlzka stringu je: " + dlzkaStringu);
return dlzkaStringu;
}
*/
public static void main(String[] kuriatko){
Metody objekt = new Metody();
String metodaVratila =
objekt.dajInfo("Popokatepetl");
System.out.println("Metoda
vratila: " + metodaVratila);
}//EndOfmain
}//EndOfClass
Ak by sme odkomentovali definíciu metódy public int
dajInfo(String s),
prekladač by nás upozornil na chybu:
Metody.java:8:
dajInfo(java.lang.String) is already defined in Metody
public int dajInfo(String s){
^
1 error
Z toho, čo sme povedali
vyššie ale plynie, že pokojne môžeme definovať metódu
public String dajInfo(int i), pretože
táto sa od pôvodnej public String dajInfo(String s) líši argumentom.
Používanie premenných inštancie
Ako o tom
budeme hovoriť podrobnejšie neskôr, každá trieda môže mať svoje premenné. Pri
vytvorení nového objektu sa inicializujú aj premenné inštancie. Dôležité je
vedieť, že metódy majú k týmto premenným prístup a môžu ich vo svojom tele
používať. Na premenné sa v metóde odvolávame bez vymenovania objektu a bez
bodky. Keď metódu v programe použijeme, bude jasné, aký objekt ju volá a aké sú
hodnoty premenných tohto objektu-inštancie.
Ilustrujme
si vyššie povedané na príklade triedy Netvor.
Kód P3.4
public class Netvor{
// premenne
instancie:
int
pocetOci;
String
menoNetvora;
// verejny
konstruktor, ktory vytvori Netvora s pozadovanym poctom oci
// a
prislusnym menom
public
Netvor(String meno,int kolkoOci){
pocetOci = kolkoOci;
menoNetvora = meno;
}
//metoda
otvorOci, ktora opisuje Netvorovo prebudzanie
// a pouziva
premenne pocetOci a menoNetvora
public void
otvorOci(){
System.out.println("Netvor " +
menoNetvora + " sa prebudza.");
for(int
i = 1; i <= pocetOci; i++){
System.out.println("Otvara
svoje " + i +". oko.");
}
}//EOotvorOci
public
static void main(String[] args){
Netvor
prvyNetvor = new Netvor("Garg",5);
Netvor
druhyNetvor = new Netvor("Monk",3);
prvyNetvor.otvorOci();
druhyNetvor.otvorOci();
}
}//EOClass
T je výstup z programu:
Netvor Garg sa prebudza.
Otvara svoje 1. oko.
Otvara svoje 2. oko.
Otvara svoje 3. oko.
Otvara svoje 4. oko.
Otvara svoje 5. oko.
Netvor Monk sa prebudza.
Otvara svoje 1. oko.
Otvara svoje 2. oko.
Otvara svoje 3. oko.
Process Exit...
Metódy jednej triedy môžu vo
svojom tele volať iné metódy tej istej triedy
Kód P3.5
public class NapisVetu {
public void
pisVetu(){
napisPodstatneMeno();
napisPrislovku();
napisSloveso();
napisZaverecnyZnak();
}
private
void napisPodstatneMeno(){
//vyberie nahodne jedno zo styroch slov a
vytlaci ho na konzolu
int i =
(int)(Math.random()*4);
switch(i){
case 0: System.out.print("Princ
");
break;
case 1: System.out.print("Jozo ");
break;
case 2: System.out.print("Robinson
Crusoe ");
break;
case 3: System.out.print("Forrest Gump
");
}
}
private void
napisPrislovku(){
//vyberie nahodne jedno zo styroch slov a
vytlaci ho na konzolu
int i =
(int)(Math.random()*4);
switch(i){
case 0: System.out.print("pomaly
");
break;
case 1: System.out.print("smutne
");
break;
case 2: System.out.print("dojate
");
break;
case 3: System.out.print("zamyslene
");
}
}
private void
napisSloveso(){
int i =
(int)(Math.random()*4);
switch(i){
case 0:
System.out.print("spieva");
break;
case 1:
System.out.print("zaspal");
break;
case 2:
System.out.print("obeduje");
break;
case 3: System.out.print("odisiel");
}
}
private void
napisZaverecnyZnak(){
int i = (int)(Math.random()*4);
switch(i){
case 0: System.out.println(".");
break;
case 1: System.out.println("?");
break;
case 2: System.out.println("!");
break;
case 3: System.out.println("...");
}
}
public
static void main(String[] args){
NapisVetu
pisar = new NapisVetu();
pisar.pisVetu();
}
Metóda
môže vo svojom tele volať aj samu seba
Toto,
takzvané rekurzívne použitie metódy treba v praxi dobre zvážiť. Často máme
nad procesom lepšiu kontrolu, respektíve ušetríme čas, ak použijeme vhodný
cyklus.
Kód P3.6
public class UsporneOpatrenia{
public void
uspor(String totoSkrat){
// najde
poziciu poslednej medzery v texte - ak existuje
int
poziciaPoslednejMedzery = totoSkrat.lastIndexOf(' ');
if(poziciaPoslednejMedzery > -1) {
//ak
tam medzera bola text skrati a vytlaci
String
skratenyText = totoSkrat.substring(0,poziciaPoslednejMedzery);
System.out.println(skratenyText);
//tu
metoda vola samu seba so skratenym textom v argumente:
uspor(skratenyText);
}
// ak
metoda medzeru v texte nenasla:
else{
System.out.println("Uz sa usetrilo
vsetko, co sa dalo.");
}
}
public
static void main(String[] args){
String
mameSa = "zijeme tu vsetci velmi veselo, obklopeni luxusom a
blahobytom";
UsporneOpatrenia skrtic = new
UsporneOpatrenia();
skrtic.uspor(mameSa);
}//EndOfmain
Výstup programu:
zijeme tu vsetci velmi veselo, obklopeni luxusom a
zijeme tu vsetci velmi veselo, obklopeni luxusom
zijeme tu vsetci velmi veselo, obklopeni
zijeme tu vsetci velmi veselo,
zijeme tu vsetci velmi
zijeme tu vsetci
zijeme tu
zijeme
Uz sa usetrilo vsetko, co sa dalo.
Metóda toString()
Je definovaná
v triede Object, umožňuje vytlačiť textovú reprezentáciu objektu. Aby táto
reprezentácia mala podobu, akú si želáme, metódu treba „prekryť“, t. j.
definovať znova. Spustite si nasledujúci kód, potom ho spustite po
odkomentovaní riadkov, definujúcich metódu toString().
Kód P3.7
// metoda toString()
public class Word {
// ako sa pise?
private String text;
// ake je dlhe?
private int dlzka;
// prislusne sety a gety....
public String getText(){
return text;
}
// konstruktor
public Word() {
System.out.println("Word,
konstruktor bez argumentov.");
}
public Word(String obsah){
text = obsah;
dlzka = text.length();
System.out.println("Konstruktor Word vytvoril slovo s textom
\" " + text + "\" a dlzkou " +dlzka);
}
public String napisOdzadu(){
StringBuffer otoc = new StringBuffer(text);
otoc = otoc.reverse();
return otoc.toString();
}
//
spusti program, potom odkomentuj nasledujuce 3 riadky a spusti ho znova
//public
String toString(){
//return text;
//}
//
public
static void main(String[] args){
Word dravec = new
Word("tiger");
System.out.println(dravec + "
odzadu: :" + dravec.napisOdzadu());
}//EOMain
}//EOClass
Cvičenia
Riešenie
Cv2.4 z minulých cvičení :
public
class Zmrzlina{
public
static void prt(String s){
System.out.println(s);
}
}//endOfClass
Pozmeňte program z Cv2.4 tak, že pri násobení
matíc budete používať metódu, ktorá vypočíta skalárny súčin vektorov. Rozšírte program o metódu „ tlacMaticu()”,
ktorá zobrazí
jednotlivé riadky matice
pod sebou.
Naprogramujte metódu ktorá zistí, či sa i-y stĺpec matice skladá –
neskladá zo samých núl.
V kóde P3.1 dopíšte cyklus, ktorý
vytlačí prezývky všetkých Kováčov. Pritom
cyklus dopredu nevie, ktoré krstné mená pre toto priezvisko sú obsadené
a ktoré nie.
Riešenia:
Riešenie Cv3.2
System.out.println("Prezyvky
Kovacov su:");
for(int meno = 0; meno < prezyvky.length ; meno++){
for(int priezvisko = 0; priezvisko < prezyvky[meno].length;
priezvisko++){
for(int prezyvka = 0; prezyvka < prezyvky[meno][priezvisko].length;
prezyvka++){
// tlac, ak sa jedna o kovaca, t.
j. o prizvisko s indexom jedna
if(priezvisko==1){
System.out.print(prezyvky[meno][priezvisko][prezyvka] + "
");
}//EOIf
}//EOFor3
}//EOFor2
}//EOFor1
System.out.println();
public class Sportka {
public
void losuj(){
//
vytvori pole 49 cisel
int[]
cisla = new int[49];
//
umiestni do nich hodnoty od 0 do 48
for(int
j = 0; j < cisla.length; j++) cisla[j] =j;
//
ide 6x losovat a tlacit vysledky
System.out.println("Vysledky
posledneho tahu sportky su: ");
//
vylosuje nahodny index, vylosovane cislo "uprace" a losuje uz len zo
zvysnych
for(int
krok = 0; krok < 6; krok++){
int nahodnyIndex = krok + (int) (Math.random()*(49 - krok));
int
totoVytlacAUprac = cisla[nahodnyIndex];
//tlaci
cislo o 1 vacsia ako je totoVytlacAUprac
System.out.print((totoVytlacAUprac+1) + " ");
//
upratuje a vymiena prvky
cisla[nahodnyIndex] = cisla[krok];
cisla[krok] = totoVytlacAUprac;
}//EndOfFor
//
odriadkuj
System.out.println();
}//EndOfMethod
public static void main(String[] args){
Sportka
hra = new Sportka();
hra.losuj();
}//EOMain
}//EOClass
© Ivan Kupka
Vaše komentáre:
kupka@fmph.uniba.sk