Cvičenie 5: Literály, null, typová konverzia, obalené typy¶
Staticko typové jazyky nám nájdu veľa chýb pri kompilácii, teda ešte pred spustením programu. Automatické kontroly typov nám dávajú pocit istoty a bezpečnosti, že náš kód je navrhnutý správne a program bude robiť to, čo očakávame.
Nič však nie je zadarmo. Statická typová kontrola so sebou prináša aj množstvo nevýhod. Aby sme v staticko typovom jazyku vedeli dobre programovať, musíme spoznať a pochopiť veci, ktoré sme pri dynamických jazykoch ako Python nemuseli riešiť.
Na dnešnom cvičení sa povenujeme práci s typmi, ale najprv si ukážeme literály jazyka a vysvetlíme si, ako Java rieši absenciu hodnoty pomocou výrazu null.
Literál¶
Dátové typy majú svoje konkrétne hodnoty. Zápis takejto hodnoty priamo v kóde sa nazýva literál. Syntax literálov je súčasťou programovacieho jazyka.
123 // int literál
123L // long literál
0xFF // int literál v hexadecimálnej sústave
0b1010 // int literál v binárnej sústave
07 // int literál v osmičkovej sústave
1_000_000 // int literál s podtržníkom (pre čitateľnosť)
3.14 // double literál
3.14f // float literál
6.022e23 // double literál s exponentom
'a' // char literál
'\n' // char literál (escape – nový riadok)
'\u03A9' // char literál (Unicode znak Ω)
"Hello" // String literál
"Line1\nLine2" // String literál s escape sekvenciou
"Unicode:\u263A" // String literál s Unicode znakom ☺
"""
Line1
Line2
""" // String literál – viacriadkový
true // boolean literál (true)
false // boolean literál (false)
null // null literál (špeciálny)
{1, 2, 3} // pole (zložený typ, prvky sú literály)
Null¶
Učím sa s pomocou umelej inteligencie
Som študent strednej školy. Učím sa Javu. Objasni mi všetky úskalia práce s null referenciou a poraď, ako sa vyhnúť problémom s null.
Typová konverzia¶
V praxi sa často stáva, že mám hodnotu, ktorú viem rovnako reprezentovať v rôznych dátových typoch alebo triedach. Najčastejšie je to pri číselných typoch. Programovacie jazyky nám rôznymi spôsobmi umožňujú konvertovať hodnoty medzi dátovými typmi. Java nám ponúka niekoľko možností.
Implicitná konverzia (widening conversion)¶
Explicitná konverzia (narrowing conversion, casting)¶
Opačne to však už automaticky nefunguje, nakoľko by sa mohla stratiť informácia. V takýchto prípadoch to vieme urobiť manuálne pomocou castingu. Pri castingu napíšeme do zátvoriek typ, do ktorého chceme skonvertovať našu hodnotu.
Pri konvertovaní na menší číselný typ môžu nastať nasledovné problémy:
- odrezanie desatinných miest
- pretečenie (overflow)
ASCII tabuľka znakov
Obalené typy¶
Autoboxing¶
Prevod z primitívneho typu na obalený sa v programovaní volá boxing (z anglického slova box ako krabica). Podobne prevod na primitívny typ sa volá unboxing.
Java vykonáva automatickú konverziu z a do balených typov, vždy keď je to potrebné. To sa v Jave nazýva autoboxing a auto-unboxing.
int x = 5;
Integer y = 10; // autoboxing, literály sú vždy primitívneho typu
y = x; // autoboxing, x je primitívny, y nie
List li = new ArrayList();
li.add(x); // autoboxing, x je primitívny typ,
// ale do listu sa dajú vkladať iba objekty
x = y; // auto-unboxing, y je objekt, x je primitívny
if(x == y) // auto-unboxing, y sa skonvertuje na primitívny typ,
// aby sme mohli porovnať hodnoty
System.out.println("x je rovnaké ako y");
Na čo si dať pozor¶
Primitívne hodnoty porovnávame pomocou operátora ==. Ak je aspoň jeden z operandov primitívna hodnota, Java urobí auto-unboxing a všetko je v poriadku. Ak však porovnávame 2 obalené objekty, musíme použiť namiesto toho metódu equals().
Konštanty a metódy obalených typov¶
Obalené triedy poskytujú množstvo užitočných metód a konštánt. Niektoré z nich si teraz predstavíme.
Triedy obalených typov poskytujú statické konštanty obsahujúce maximálne a minimálne hodnoty a tiež špeciálne hodnoty ako napríklad nekonečno.
Metódy tried obalených typov sa často používajú na typovú konverziu s triedou String, teda na prevody z a do reťazcov.
String s = "11001";
int x = Integer.parseInt(s); // prevod z reťazca do int
int c = Integer.parseInt(s, 2); // vieme robiť prevod aj z inej číselnej sústavy
long y = Long.parseLong(s); // prevod z reťazca do long
byte b = Byte.parseByte(s); // Vyhodí NumberFormatException výnimku,
// pretože číslo je príliš veľké na byte
long a = 1234;
String s10 = Long.toString(a); // prevod do reťazca
String s16 = Long.toString(a, 16); // vieme si vybrať číselnú sústavu
System.out.printf("Číslo %s v šestnástkovej sústave je %s", s10, s16);
Úlohy na precvičenie¶
Úloha 5.1: Bezpečné porovnanie reťazcov
Napíš metódu, ktorá porovnáva dva reťazce aj v prípade, že jeden alebo oba sú null.
Výstup: true, ak sú rovnaké (vrátane oboch null), inak false.
Úloha 5.2: Číselné sústavy
Napíšte program, ktorý načíta celé číslo z klávesnice a vypíše ho v desiatkove, šestnástkovej, osmičkovej a dvojkovej sústave.
Bonus: Ak je číslo v správnom rozsahu, napíšte aj, aký znak by toto číslo mohlo reprezentovať.
Úloha 5.3: Detekcia číselného typu
Napíš program, ktorý načíta reťazec z klávesnice. Potom program skúsi tento reťazec skonvertovať do rôznych číselných typov a uvedie, ktoré typy by mohli načítaný reťazec reprezentovať.
Pri práci použite ošetrenie výnimiek.
Najprv vyskúšajte typy long a double. Môžete pridať menšie celočíselné typy.
Bonus: Skúste otestovať aj šestnástkovú, binárnu a osmičkovú sústavu.
Úloha 5.4: Delenie
Napíš program, ktorý načíta dve čísla a napíše výsledok po delení. Ošetrite čo najviac výnimiek pri chybách, ktoré môžu nastať.
Úloha 5.5: Ošetrená kalkulačka
Napíšte program, v ktorom užívateľ bude môcť vykonať základné matematické operácie. Program rozdeľte do viacerých metód.
Vypisujte menu a po splnení úlohy sa do neho naspať vráťte. Majte možnosť ukončiť program.
Zhrnutie cvičenia¶
- Literál je zápis konkrétneho údaja priamo v kóde
- Špeciálny literál
nullvyjadruje neprítomnosť hodnoty- Akákoľvek premenná referenčného (neprimitívneho) typu môže nadobúdať hodnotu
null - Používa sa, ak pri inicializácii premennej ešte nemáme vypočítanú hodnotu, ak chceme vyjadriť neprítomnosť hodnoty, alebo ak chceme z premennej vymazať objekt
- Ak kód očakáva objekt a dostane null hodnotu, nemôže pokračovať a vyhodí výnimku
NullPointerException(NPE). - Metóda
Objects.requireNonNull()slúži na ošetrenie vstupov pri kontrolenullhodnôt
- Akákoľvek premenná referenčného (neprimitívneho) typu môže nadobúdať hodnotu
- Typová konverzia nám v Jave umožňuje konvertovať hodnoty medzi dátovými typmi
- Implicitná konverzia - widening, automaticky konvertuje menšie typy na väčšie
- Explicitná konverzia - narrowing alebo casting, manuálna konverzia, pri ktorej môže nastať strata informácie orezaním alebo pretečením
- Znakový typ
charviem previesť naintalebo väčší, pretože znaky sú vnútorne reprezentované ako číselné kódy - Základné štandardy znakových kódov sú ASCII a Unicode
- Obalené typy - wrapper classes
- Pre každý primitívny dátový typ existuje príslušný obalený typ
- Obalený typ je trieda a jeho hodnoty sú objekty
- Autoboxing a auto-unboxing je automatická konverzia z a do balených typov, vždy keď je to potrebné
- Uprednostňujeme primitívne typy a obalené typy používame len keď je to nutné
- Ak porovnávame 2 obalené objekty, musíme použiť metódu
equals(), nie== - Obalené triedy poskytujú pomocné metódy ako
parseLong(),toString()a rôzne konštanty
Poznámky do zošita
V zošite je potrebné mať napísané aspoň tieto poznámky:
LITERÁL
Literál je zápis údaja priamo v kóde
Literál null vyjadruje neprítomnosť hodnoty
Výnimka NullPointerException sa vyhodí, ak program očakával objekt a nie null
TYPOVÁ KONVERZIA
Typová konverzia umožňuje konvertovať medzi dátovými typmi
Implicitná konverzia - widening, automaticky konvertuje menšie typy na väčšie
byte → short → int → long → float → double
Explicitná konverzia - narrowing alebo casting, manuálna konverzia
char viem previesť na int alebo väčší, pretože znaky sú vnútorne ako číselné kódy
OBALENÉ TYPY
Obalené typy - wrapper classes
Pre každý primitívny dátový typ existuje príslušný obalený typ - trieda
Autoboxing a auto-unboxing je automatická konverzia z a do balených typov, keď je to potrebné
Uprednostňujeme primitívne typy pred obalenými, Java robí konverzie za nás
2 obalené objekty porovnávam cez equals()
Skúšanie a kontrola vedomostí
Okruhy otázok na test:
- Na čo slúži literál null, aká výnimka sa s ním spája
- Ako funguje implicitná typová konverzia
- Čo je a ako sa robí explicitná typová konverzia
- Čo sú obalené typy, aké majú použitie
- Čo je autoboxing a auto-unboxing
- Ako sa parsujú čisla z reťazca znakov a ako sa prevádzajú čísla na reťazec