Syntax jazyka Java - dátové typy, operátory
Základy informatiky - jazyk Java
Úvod do programovania v jazyku Java
- >Syntax jazyka Java
>Syntax jazyka Java - dátové typy, operátory
>Syntax jazyka Java - riadiace príkazy
>Syntax jazyka Java - základné triedy
>Java - polia
>Java - vstup a výstup údajov
Java - objektovo orientovaný prístup
Vzorové príklady:
Java - implementácia numerických algoritmov
Java - triedy geometrických tvarov
Pokročilé témy:
Obsah
Dátové typy
Tvrdenie, že Java je úplne objektovo orientovaná nie je pravdivé. Od úplnému objektovo orientovaného prístupu k tvorbe programov ju delí 8 základných primitívnych dátových typov. Sú to úplne bežné dátové typy, tak ako ich poznáme z iných jazykov: char, byte, short, int, long, float, double a boolean. Slúžia na uchovávanie a manipuláciu so znakmi, číslami celými aj číslami s plávajúcou desatinnou čiarkou a konečne potom s logickými hodnotami. Rozdiel pri práci s objektovým dátovým typom a primitívnym dátovým typom je ten, že objekt sa vytvorí vo voľnej pamäti, ktorej sa hovorí hromada (halda, heap), kdežto primitívny dátový typ sa vytvorí v zásobníku (stack). Práca so zásobníkom je rýchlejšia ako s haldou.
Typ char slúži pre uchovanie jedného znaku, typy byte, short, int a long sa používajú pre celé čísla, float a double pre reálne čísla (presnejšie pre čísla s plávajúcou desatinou čiarkou) a boolean pre uchovanie logických hodnôt.
Numerický rozsah je určený dátovým typom, ktorý určuje aj veľkosť priestoru, ktorý je pre premennú vyhradený v pamäti počítača. Pre primitívne dátové typy potom platí nasledujúce
- pamäťové miesta v pamäti počítača svojim stavom reprezentujú určitú informáciu
- každá premenná v programe má dátový typ - určuje počet vyhradených pamäťových miest pre ňu
- základná jednotka informácie - bit má dva stavy: 0/1
- dátový typ boolean má hodnoty true, false
- minimálne adresovateľné množstvo informácie v pamäti je 8 bitov, aj boolean je (väčšinou) 8 bitov
- štandardne sa používa byte = 8 bitov ([math]2^8 = 256[/math] stavov)
- 8 bitov v pamäti možno interpretovať ako binárne číslo s hodnotou n=0..255
- celé číslo v rozsahu -128..127 (1. bit je znamienko) - v Jave typ byte
- n-tý znak v tabuľke ASCII
- inštrukciu číslo n v strojovom kóde
- farbu číslo n v palete obrázka
- a podobne ...
- v 2 bytoch (216 = 65536 stavov) možno uchovávať číslo v rozsahu 0..65535
- celé číslo v rozsahu -32768..32767 (typ short)
- znak v UNICODE (typ char)
- v 4 bytoch sa uchováva číslo v rozsahu -2147483648..2147483647 (typ int)
- reálne číslo typu float
- v 8 bytoch sa uchováva celé číslo typu long
- reálne číslo typu double
Základné vlastnosti primitívnych dátových typov zhŕňa nasledujúca tabuľka:
Primitivny typ | Veľkosť | Minimálna hodnota | Maximálna hodnota | Implicitná hodnota | Obalová trieda |
char | 16 bitov | Unicode 0 | Unicode 65 535 ([math]2^16 -1[/math]) | '\u0000' (null) | Character |
byte | 8 bitov | - 128 ([math]- 2^7[/math]) | + 127 ([math]2^7 -1[/math]) | (short)0 | Byte |
short | 16 bitov | - 32 768 ([math]- 2^{15}[/math]) | + 32 767 ([math]2^{15} -1[/math]) | (short)0 | Short |
int | 32 bitov | - 2 147 483 648 ([math]- 2^{31}[/math]) | + 2 147 483 647 ([math]2^{31} -1[/math]) | 0 | Integer |
long | 64 bitov | - 9 223 372 036 854 775 808 ([math]- 2^{63}[/math]) | + 9 223 372 036 854 775 807 ([math]2^{63} -1[/math]) | 0L | Long |
float | 32 bitov | ANSI IEEE.754 | ANSI IEEE.754 | 0.0f | Float |
double | 64 bitov | ANSI IEEE.754 | ANSI IEEE.754 | 0.0d | Double |
boolean | false | Boolean | |||
void | Void |
Iste ste si všimli niekoľkých zvláštností. Jednak Java nepozná typy "so znamienkom" a "bez znamienka" - teda signed a unsigned. Ďalej, Java používa pre reprezentáciu znakov (a teda i reťazcov) kódovanie Unicode. Vďaka nemu môžeme pracovať so symbolmi väčšiny znakových sád. Z toho dôvodu je znak uložený v dvoch bytoch.
Java navyše obsahuje dátový typ, ktorý sa v jazyku C / C++ nevyskytoval - typ boolean. Premenná tohto typu môže nadobúdať dvoch hodnôt - true (pravda) alebo false (nepravda).
V tabuľke je ešte jeden "dátový" typ - void. Ten nenesie žiadnu informáciu a znamená niečo ako "prázdno". Používa sa ako návratový typ metód, ktoré nevracia žiadnu (normálnu) hodnotu.
Ďalšie zaujímavý stĺpček tabuľky je "Obalová trieda". Ku každému primitívnemu dátovému typu existuje aj trieda, ktorá obsahuje metódy pre prácu s premennými týchto typov. V Jave ešte existujú ďalšie dve triedy pre prácu s číslami: java.math.BigInteger a java.math.BigDecimal, ktoré sa používajú na presné výpočty s celými a desatinnými číslami. Veľkosti a rozsahy čísel sú zaručené na všetkých systémoch. Aritmetika je určená normou ANSI IEEE.754[1] z roku 1985, čomu zodpovedá aj rozsah typov float a double. Navyše sú v triedach Double a Float definované konštanty NEGATIVE_INFINITY, POSITIVE_INFINITY a NaN - teda kladné a záporné nekonečno a konštanta udávajúca, že výsledkom operácie nie je číslo (Not a Number). Práca s týmito novými hodnotami nie je nijako špeciálna. Delenie nulou vždy vyprodukuje nekonečno, delenie nekonečnom vyprodukuje nulu a ak sa treba snažíme vynásobiť nekonečno nulou, vyjde nám výsledok ako NaN.
Reprezentácia celočíselného dátového typu
Pri niektorých operáciách (zmena typov, aritmetické operácie ...) je vhodné vedieť niečo o tom, ako sú informácie uložené v pamäti. Pre celočíselné dátové typy si to ukážeme na príklade dátového typu byte[2].
- 1 bit určuje znamienko čísla
- 7 bitov celé číslo 0..127
- vždy nasledujúce číslo získame pripočítaním 1 k predošlému
- pri výpočte 127 + 1 = -128 dôjde k "pretečeniu", jednotka, ktorá sa dostala na miesto znamienka spôsobí skok
- podobný prípad nastane pri výpočte - 1 + 1 = 0, dôjde k "pretečeniu" a jednotka sa dostane mimo bitov" danej premennej, výsledok je nula v každom bite
čísla sú za sebou zoradené takto:
bity | hex | číslo |
0000 0000 | 00 | 0 |
0000 0001 | 01 | 1 |
0000 0010 | 02 | 2 |
0000 0011 | 03 | 3 |
... | ... | ... |
0000 1111 | 0f | 15 |
... | ... | ... |
0111 1111 | 7f | 127 |
1000 0000 | 80 | -128 |
1000 0001 | 81 | -127 |
... | ... | ... |
1111 1111 | ff | -1 |
Reprezentácia reálnych dátových typov
Reálne dátové typy sú v pamäti počítača uložené v semilogaritmickom tvare[1]. Formmát pre základný typ float má tvar
- 1 bit určuje znamienko čísla
- 8 bitov reprezentuje exponent (-128...127)
- ostatné bity reprezentujú tzv. mantisu: desatinné číslo [math]d = \sum{b_i 2^{-i}}[/math]
- číslo sa vždy upraví tak, aby malo tvar [math]1.1001101 \dots \times 2^{exp}[/math] a zapisujú sa len jednotky za desatinnou bodkou
Zložitejšie dátové typy sú objekty, sú konštruované pomocou primitívnych dátových typov, predstavujú komplikovanejšiu informáciu ako len uchovanie hodnoty. Budeme sa nimi zaoberať neskôr.
Premenné a konštanty
objekt ukladá svoje stavy vo svojich vlastnostiach. Avšak, programovací jazyk Java používa taktiež termín "premennej". Pre pomenovávanie premenných platia nasledujúce pravidlá:
- U názvov premenných záleží na veľkosti písmen. Názov premennej sa môže skladať z ľubovoľného platného znaku - dĺžkovo neobmedzená sekvencie Unicode znakov a čísiel - ktoré musia začínať písmenom, znakom dolára "$" alebo znakom podčiarkovníka "_". Konvenciou však je, že meno premennej vždy začína písmenom, nie dolárom či podčiarknikom.
- Prázdne miesto v názve premennej nie je povolené.
- Nasledujúce znaky môžu byť písmená, číslice, znaky dolára alebo podčiarknutia. Keď vyberáme meno pre premennú, používame plná mená ako kryptografické skratky. Používanie plných mien premenných často to vytvára kód, ktorý sám hovorí, čo robí; mená vlastností Cadence, speed a gear, napríklad, sú oveľa viac porozumitelné, ako ich skratky, ako sú s, c a g.
- Názov premennej nesmie byť ž existujúce kľúčové jazyka Java.
- Ak sa názov vašej premennej pozostáva iba z jedného slova, píšte toto meno celej malými písmenami. Konvencia hovorí o nasledujúcich pravidlách:
- Ak obsahuje viac ako jedno slovo, zväčšite každé prvé písmeno nasledujúceho slova. Názvy gearRatio a currentGear sú ukážkovými príkladmi tejto konvencie.
- Ak vaša vlastnosť obsahuje konštantnú hodnotu, ako je napríklad static final int NUM_GEARS = 6; Názov premennej by mal byť z veľkých písmen, slová sú oddelené podčiarknikom. Podľa konvencie sa podčiarkovník nepoužíva nikde inde.
Premenné deklarujeme nasledujúcim spôsobom:
typ nazovPremennej[=hodnota];
kde:
- typ - je názov primitívneho dátového typu
- nazovPremennej - je názov premennej. Názvy premenných volíme podľa predchádzajúcich pravidiel.
- časť v hranatých zátvorkách je nepovinná. Je to inicializácia premennej
- premennej pri deklarácii môžeme priradiť hodnotu.
- Dátový typ hodnoty musí rešpektovať typ premennej.
Typy premenných
V programovacom jazyku Java máme nasledovné druhy premenných:
- Premenné inštancie (nestatické vlastnosti)
- Objekty ukladajú svoje individuálne stavy do "nestatických vlastností", čo sú vlastnosti definované bez kľúčového slova static. Nestatické vlastnosti sú taktiež známe ako premenné inštanicie, pretože ich hodnoty sú jedinečné pre každú inštanciu triedy (inými slovami, pre každý objekt); vlastnosť currentSpeed obejktu bicyklel1 je nezávislá na vlastnosti currentSpeed objektu bicyklel2.
- Premenné triedy (statické vlastnosti)
- Premenné triedy sú vlastnosti, u ktorých bol uvedený modifikátor static; tento modifikátor hovorí kompilátoru, že táto vlastnosť má existovať iba raz, nezávisle na tom, koľko objektov tejto triedy bolo vytvorené. Vlastnosť definujúca počet prevodov na bicykli môže byť definovaná s kľúčovým slovom static, pretože počet prevodov majú všetky kolesá rovnaký. Kód static int numGears = 6; túto statickú vlastnosť vytvorí. Prípadne môže byť pridelené kľúčové slovo final (definuje konštantu), aby bolo zaručené, že sa v priebehu programu počet prevodov nezmení.
- Lokálne premenné
- Rovnako ako objekt ukladá svoje stavy do vlastností, metóda ukladá svoje dočasné stavy do lokálnych premenných. Syntax ktorá definuje lokálnu premennú je úplne rovnaká ako deklarácia vlastnosti (napr. int count = 0;). Neexistuje žiadne kľúčové slovo hovoriace, že premenná je lokálna; kompilátor to spozná podľa umiestnenia deklarácie. Lokálne premenná sa deklaruje vnútri zložených zátvoriek, vymedzujúcimi metódu. Z toho navyše vyplýva, že lokálne premenné môže využiť len metóda, ktorá ich definuje. Žiadna iná časť triedy k nim nemá prístup.
- Parameter
- Parametre majú súvis s metódami danej triedy. Sú to vlastné vstupné premenné metódy, pomocou ktorých metóda získava vstupné údaje. Je dôležité si uvedomiť, že parametre sú kvalifikované ako "premenné", nie ako "vlastnosti".
Použitie premenných v programe
Použitie dátových typov si môžete vyskúšať na nasledujúcom príklade.
class TestPrem{
public static void main(String[] args) {
byte k; // len deklaracia
int i=0xff; // hexadecimalna sustava, definujeme i=255
// double pi=3.14159265358979;
// Ako si zapamatat hodnotu pi - pocitajte pismena v slovach:
// I want a drink, alcoholic of course after the
// heavy lectures involving quantum mechanics.
double pi = Math.acos(-1);
boolean b = true; // false
float fl = 1.11f; // f je potrebne
char c ='\u0041'; // v unicode
String s = "moze obsahovat viac pismen a slov"; //retazec
//System.out.println("Hodnota premennej k : "+k); // nemoze byt pred
k=(byte) i; // musi byt pretypovane
System.out.println("Hodnota premennej c : " + c);
System.out.println("Hodnota premennej k : " + k);
System.out.println("Hodnota premennej pi: " + pi);
System.out.println("Hodnota premennej s : " + s);
}
}
Môžeme si teraz povedať niečo o použitej funkcii System.out.println. V zátvorkach je uvedený jej parameter - reťazec, ktorý sa vypíše na výstup (štandardne konzola). Túto funkciu budeme používať často, lebo je to najjednoduchší spôsob ako dostať informáciu o tom, ako beží program a aké hodnoty majú prememnné.
Spomínaná funkcia taktiež ilustruje vyžitie objektov, bez ktorých sa v Jave nezaobídeme. Že pracujeme s objektami rozoznáme na základe bodiek, ktoré oddeľujú "úrovne" daného objektu. T.j. operačný systém ako objekt (System) má v sebe objekt výstup (out = output) a ten vie vykonať výpis (println = print line). Podobne Math v sebe obsahuje funkciu arkuskosínus (acos - príklad ilustruje, že pri definícii môžeme využiť funkčnú hodnotu).
Pretypovanie (byte) znamená, že sa na byty premennej i (celé číslo v pamäti zaberajúce 4 byty) počítač pozrie ako by mala iný typ (popzrie sa len na najnižší 1 byte, ostatné ignoruje). Musíme pri tom pamätať na to, že môžeme dostať "prekvapujúce" výsledky.
Často je možné sa pretypovaniu vyhnúť, niekedy to však bez neho nejde. Mnohokrát ho vykoná kompilátor za nás, preto je "skryté": pri použití znamienka + medzi reťazcom a číslom sa najskôr číslo pretypuje na reťazec (vytvorí sa z neho) a oba reťazce sa spoja. Podobne je to aj pri aritmetických operáciách s číslami - napr. ak máme výraz, v ktorom vystupujú len celé čísla, aj delenie bude celočíselne, ak však aspoň jeden z operandov je double, delenie bude reálne.
Na výstupe zistíme, že premenné majú hodnoty A, -1, 3.141592653589793. ( (byte)255 = -1 je vďaka reprezentovaniu premennej typu byte, viď vyššie)
Operátory
Operátory slúžia na vykonanie určitej akcie s premennými: aritmetické operácie, porovnanie, priradenie hodnoty (pozri príklad). V nasledujúcej tabuľke uvádzame prioritu operátorov v jazyku Java.
Poradie | Skupina | Operátory |
---|---|---|
1 | postfixové | [] . (parametry) op++ op-- |
2 | unárne | ++op --op +op -op ~ ! |
3 | vytvárania a pretypovania | new (typ) |
4 | multiplikatívne | * / % |
5 | aditívne | + - |
6 | binárne posuny | << >> >>> |
7 | relačné | > >= <= < instanceof |
8 | ekvivalencia / nonekvivalencia | == != |
9 | bitové AND | & |
10 | bitové XOR | ^ |
11 | bitové OR | | |
12 | logické AND | && |
13 | logické OR | || |
14 | ternárny | ?: |
15 | priradenie | = += -= *= /= %= ^= &= |= <<= >>= >>>= |
Všimnite si zatiaľ predovšetkým, že násobenie má vyššiu prioritu, ako sčítanie a odčítanie, porovnávanie naopak nižšiu:
class priorita {
public static void main(String args[]) {
System.out.println("2*3 + 5 = " + 2*3+5 ); // 65
System.out.println("2*3 + 5 = " + (2*3+5) ); // 11
System.out.println("2*(3 + 5) = " + 2*(3+5) ); // 16
System.out.println("2+3 == 5 = " + (2+3==5) ); // true
//System.out.println("2+3 == 5 = " + 2+3==5 ); // chybne
}
}
V prvom riadku sa najskôr k reťazcu pripojí 6 a potom 5. V druhom riadku sa najskôr čísla sčítajú a výsledok (11) sa pripojí k reťazcu. Sčítanie môžeme uprednostniť pred násobením ako sme zvyknutí použitím zátvoriek. V štvrtom riadku sa najskôr vykoná sčítanie čísel a výsledok sa porovná s pravou stranou, výsledkom je logická hodnota true. Posledný zakomentovaný riadok je vďaka nízkej priorite operátora porovnávania chybný a nedá sa skompilovať.
Príklad - Priorita aritmetických operátorov
class operator {
public static void main(String[] args) {
int i,j,k;
i=5; j=10;
k=i+++j;
System.out.println(i+","+j+","+k);
i=5; j=10;
k=(i++)+j;
System.out.println(i+","+j+","+k);
i=5; j=10;
k=i+(++j);
System.out.println(i+","+j+","+k);
}
}
Výstup bude : 6,10,15 ; 6,10,15 ; 5,11,16. Teda prvý a druhý príkaz sú identické (vyššiu prioritu má postinkrementácia ako sčítanie). V treťom prípade pomocou zátvoriek uprednostníme preinkrementáciu. Príklady možno prepísať bez použitia operátora ++: Prvý a druhý prípad: k = i + j; i = i + 1; Tretí prípad: j = j + 1; k = i + j;
Odkazy
- ↑ 1,0 1,1 ANSI IEEE.754 http://steve.hollasch.net/cgindex/coding/ieeefloat.html
- ↑ Reprezentácia celých čísel - http://en.wikipedia.org/wiki/Signed_number_representations
- Java tutoriál - http://programujte.com/?akce=clanek&cl=2007050202-java-tutorial-promenne-4-dil-
- Začíname v Javě - http://casopis.programator.cz/r-art.php?clanek=199