Cvičenie 4: Balíky a triedy, polia, varargs¶
Na dnešnom cvičení sa bližšie povenujeme poliam, ktoré predstavujú základný spôsob ako v Jave uchovávať dokopy viac hodnôt. Pred tým si však vyskúšame vytvoriť projekt s viacerými triedami.
Projekt s viacerými triedami v balíkoch¶
V IntelliJ IDEA si v našom projekte vytvoríme balíky a 4 triedy podľa nasledovného príkladu
package sk.spse.tvary;
public class Kruh {
public static double obvod(double r) {
return 2 * Math.PI * r;
}
public static double obsah(double r) {
return Math.PI * r * r;
}
}
package sk.spse.tvary;
public class Obdlznik {
public static int obvod(int a, int b) {
return (2 * a) + (2 * b);
}
public static int obsah(int a, int b) {
return a * b;
}
}
package sk.spse.tvary;
public class Stvorec {
public static int obvod(int a) {
// Ak je trieda v tom istom balíku, nemusím písať jeho názov
return Obdlznik.obvod(a, a);
}
public static int obsah(int a) {
return Obdlznik.obsah(a, a);
}
}
package sk.spse;
import sk.spse.tvary.Kruh;
public class Main {
public static void main(String[] args) {
int a = 10;
// Používam triedu Kruh, ktorú som si importoval
System.out.printf("Obvod kružnice o veľkosti %d je %.2f\n",
a, Kruh.obvod(a));
// Ak použijem celé meno triedy, nemusím robiť import
System.out.printf("Obvod štvorca o veľkosti %d je %d\n",
a, sk.spse.tvary.Stvorec.obvod(a));
}
}
Pole - Array¶
Ak chceme v Jave uchovávať viac hodnôt v jednej premennej, môžeme použiť pole.
Pole (anglicky array) je zoznam hodnôt jedného typu s fixnou (nemennou dĺžkou). Jednotlivé hodnoty sú očíslované a vieme k nim pristupovať pomocou indexu. Ide o neprimitívny dátovy typ, teda konkrétne pole je objekt. Na prácu s poliami máme v Jave špeciálnu syntax.
Vlastnosti poľa:
- fixná veľkosť, nemenná dĺžka
- samotné prvky poľa ale meniť viem
- homogénne prvky - prvky poľa musia byť rovnakého typu
- pole je objekt, nie je primitívny typ. Prvky poľa môžu byť primitívne.
- prvky majú poradie, majú index, ktorý začína číslom 0
Pri vytváraní poľa musím definovať jeho veľkosť.
Pole viem vytvoriť aj priamo z konkrétnych hodnôt
Ak mám pole primitívnych hodnôt, tak sú uložené priamo v objekte poľa. Ak mám však pole neprimitívnych hodnôt - objektov, tak do objektu poľa sa uložia referencie na objekty. V nasledujúcom príklade si pomocou diagramu znázorníme, ako to vyzerá v pamäti počítača:
premenná, pole a jednotlivé prvky poľa sú v pamäti počítača uložené samostatne
Používanie poľa¶
Dĺžku poľa viem zistiť pomocou atribútu length
K jednotlivým prvkom poľa pristupujem pomocou hranatých zátvoriek. Takto viem hodnoty prvkov nie len čítať ale ich aj meniť.
Ak sa pokúsim pristúpiť ku neexistujúcim prvkom, Java vyhodí výnimku ArrayIndexOutOfBoundsException
Prvky poľa viem prechádzať v cykle. Môžem použiť klasický for alebo novší for-each
Prvky poľa môžu byť akéhokoľvek typu, primitívneho aj neprimitívneho.
Užitočné utility¶
Niektoré veci sa pri poliach robia špeciálne. Polia sa nedajú porovnávať cez klasický equals() a nedajú sa vypisovať do reťazca cez klasický toString(). Tak isto pri kopírovaní poľa pozor. Keďže pole je objekt, obyčajné = skopíruje referenciu (odkaz), ale objekt bude ten istý.
Pre takéto situácie máme v Jave pomocnú triedu java.util.Arrays, v ktorej máme užitočné utility. Všetky metódy sú statické.
Arrays.fill(pole, hodnota)- vyplní pole hodnotouArrays.equals(pole1, pole2)- porovná polia podľa ich hodnôtArrays.toString(pole)- vypíše obsah poľa do reťazcaArrays.sort(pole)- zoradí pole od najmenšieho po najväčší prvok. Mení existujúce pole!
Dokumentácia
Všetky utilitky nájdete v oficiálnej dokumentácii triedy java.util.Arrays
Kopírovanie poľa¶
Na vytvorenie kópie poľa máme v Jave viacero metód.
pole.clone()- vytvorí nové pole a skopíruje hodnoty prvkovArrays.copyOf(pole, novaDlzka)- nové pole môže mať inú veľkosťArrays.copyOfRange(pole, od, do)- môžeme skopírovať iba časť poľaSystem.arraycopy(src, srcPos, dest, destPos, length)- skopíruje hodnoty prvkov medzi dvoma existujúcimi poľami
Shallow copy
Tieto metódy kopírovania poľa sú tzv. povrchné, anglicky shallow. To znamená, že pole sa síce vytvorí nové a prvky
sa do neho skopírujú, ale samotné prvky sú iba obyčajná kópia ako pri =. To znamená, že keď máme pole objektov, tak sa nám skopírujú referencie. Vo výsledku budem mať 2 rozdielne polia, ale prvky v nich budú ukazovať na rovnaké objekty. To môže byť problém, ak sú objekty meniteľné.
Na príklade s poľom slovo si ukážeme, ako sa pri kopírovaní poľa jeho jednotlivé prvky zdieľajú.
Pole neprimitívnych hodnôt vytvára pri kopírovaní tzv. Shallow copy
Viacrozmerné pole¶
V Jave viem vytvoriť aj viacrozmerné polia. Sú komplikovanejšie na pochopenie, spomenieme ich preto iba veľmi stručne.
Učím sa s pomocou umelej inteligencie
Som študent strednej školy, učím sa Javu. Vysvetli mi základy viacrozmerných polí v Jave, uveď príklady a na čo si dávať pri práci s viacrozmernými poľami pozor.
Premenlivý počet argumentov¶
V Jave vieme definovať metódy, ktoré majú premenlivý počet argumentov. Takéto argumenty sa anglicky volajú varargs (variable-length arguments) a pri volaní takejto metódy môžeme uviesť akýkoľvek počet premenlivých argumentov (aj 0). Samozrejme, ak má metóda aj klasické argumenty, tie musíme uviesť vždy.
V metóde môžeme mať iba jeden vararg argument. Premenlivý argument musíme uviesť v zozname parametrov metódy vždy ako posledný. V tele samotnej metódy máme vararg argument uložený vo forme poľa.
Keďže vararg argument je v skutočnosti pole hodnôt, vieme pri volaní takejto metódy poslať na vstup pole, a Java ho automaticky použije ako pole argumentov.
Učím sa s pomocou umelej inteligencie
Som študent strednej školy, učím sa Javu. Vysvetli mi ako sa v Jave pracuje s varargs.
Úlohy na precvičenie¶
Úloha 4.1: Priemer
V balíku sk.spse.util vytvorte triedu Math. V tejto triede vytvorte statickú metódu priemer, ktorá má na vstupe pole čísel a vráti ich aritmetický priemer. Zavolaj ju z metódy sk.spse.Main.main()
Úloha 4.2: Najdlhší reťazec
V balíku sk.spse.util vytvorte triedu Pole. V nej vytvorte statickú metódu najdlhsiRetazec, ktorá má na vstupe pole reťazcov a vráti najdlhší z nich.
Úloha 4.3: Medián
V triede sk.spse.util.Math vytvorte statickú metódu median, ktorá má premenlivý počet číselných argumentov, a vráti ich mediánovú hodnotu.
Medián je číslo, ktoré leží presne v strede zoradeného zoznamu čísel. Ak je dĺžka zoznamu párna, mediánom je priemer dvoch stredných čísel.
Úloha 4.4: Medián z klávesnice
Do predchádzajúcej úlohy pridajte do metódy sk.spse.Main.main() načítavanie čísel z klávesnice. Ako budete riešiť počet čísel?
Úloha 4.5: Párne a nepárne
V triede sk.spse.util.Pole vytvorte statickú metódu parneNeparne, ktorá má na vstupe pole čísel, a vráti pole o veľkosti 2, kde prvý prvok poľa bude počet párnych čísel a druhý prvok bude počet nepárnych čísel.
Úloha 4.6: Spájanie polí
V triede sk.spse.util.Pole vytvorte statickú metódu spoj, ktorá má na vstupe dve polia a vráti pole, ktoré vznikne spojením týchto dvoch polí.
Úloha 4.7: Najdlhšia sekvencia
V triede sk.spse.util.Pole vytvorte statickú metódu najdlhsiaSekvencia, ktorá má na vstupe pole a vráti číslo, ktorého hodnota je dĺžka najdlhšej sekvencie rovnakých prvkov vo vstupnom poli.
Zhrnutie cvičenia¶
- Import tried v Jave nie je povinný, stačí ak použijeme celý názov triedy
-
import static balik.Trieda.*importuje všetky statické metódy danej triedy - V Jave sa nedá vytvoriť alias, ak je problém s duplicitou, používame celý názov triedy
-
- Pole - Array, je zoznam hodnôt jedného typu
- fixná veľkosť
- hodnoty prvkov meniť viem
- všetky prvky musia mať rovnaký typ
- pole je objekt
- prvky majú poradie, index
- Ak prvky poľa sú primitívne, ukladajú sa priamo do poľa. Ak sú objekty, v poli sú iba referencie na nich.
- Pri vytváraní poľa musím uviesť jeho veľkosť, napr.
int[] pole = new int[5];- Pole viem inicializovať aj konkrétnymi hodnotami, napr.
int[] pole = {1, 2, 3, 4, 5}; - K prvkom poľa pristupujem cez index, napr.
pole[0] = 3; - Dĺžku poľa zistím cez atribúť
length, napr.pole.length - Pole viem iterovať v cykle
for-each
- Pole viem inicializovať aj konkrétnymi hodnotami, napr.
- Pri poliach si treba dávať pozor hlavne na tieto veci
- Klasický
equals()nefunguje správne - Klasický
toString()nevypíše hodnoty prvkov - Keďže pole je objekt, operátor
=skopíruje referenciu (odkaz), nie objekt
- Klasický
- Užitočné utility nájdem v triede
java.util.Arrays-
Arrays.fill(pole, hodnota)- vyplní pole hodnotou -
Arrays.equals(pole1, pole2)- porovná polia podľa ich hodnôt -
Arrays.toString(pole)- vypíše obsah poľa do reťazca -
Arrays.sort(pole)- zoradí pole od najmenšieho po najväčší prvok. Mení existujúce pole!
-
- V Jave mám metódy na povrchné (shallow) kopírovanie poľa
-
pole.clone()- vytvorí nové pole a skopíruje hodnoty prvkov -
Arrays.copyOf(pole, novaDlzka)- nové pole môže mať inú veľkosť -
Arrays.copyOfRange(pole, od, do)- môžeme skopírovať iba časť poľa -
System.arraycopy(src, srcPos, dest, destPos, length)- skopíruje hodnoty prvkov medzi dvoma existujúcimi poľami
-
- Viem vytvárať aj viacrozmerné polia
-
int[][] matica = new int[2][3]; -
matica[0][0] = 1; -
int[][] matica2 = {{1, 2, 3}, {4, 5, 6}};
-
- Metódy v Jave môžu mať premenlivý počet argumentov - varargs
- Príklad definície
void metoda(int a, int b, String... slova) - V tele metódy sú argumenty uložené do poľa
- Do vararg metódy viem vložiť aj pole, Java ho použije ako pole argumentov
- Príklad definície
Poznámky do zošita
V zošite je potrebné mať napísané aspoň tieto poznámky:
POLIA
Pole - Array, je zoznam hodnôt jedného typu
Vlastnosti:
- fixná nemenná veľkosť
- hodnoty prvkov meniť viem
- všetky prvky musia mať rovnaký typ
- pole je objekt
- prvky majú poradie, index
Pri vytváraní poľa musím uviesť jeho veľkosť, napr. int[] pole = new int[5];
Inicializácia konkrétnymi hodnotami, int[] pole = {1, 2, 3, 4, 5};
K prvkom poľa pristupujem cez index, pole[0] = 3;
Dĺžku poľa zistím cez pole.length
Pole viem iterovať vo for-each
Pole kopírujem cez pole.clone()
Utility v triede java.util.Arrays
- Arrays.equals
- Arrays.toString
- Arrays.sort
- Arrays.copyOf
Viacrozmerné polia int[][] matica new int[2][3];
VARARGS
Varargs - premenlivý počet argumentov pri volaní metódy
Príklad definície void metoda(int a, int b, String... slova)
V tele metódy sú tieto argumenty uložené do poľa
Ak ako vararg argument uvediem pole, použije sa ako pole argumentov
Skúšanie a kontrola vedomostí
Okruhy otázok na test:
- Čo je pole
- Vlastnosti poľa
- Ako zistím dĺžku poľa
- Ako kopírujem pole
- Ako porovnám 2 polia
- Varargs - čo to je
- Ako sa pristupuje k varargs vnútri metódy?

