Ve čtvrtém díle překladu oficiálního Java tutoriálu se zaměříme na samotné programování, nejdříve na proměnné.
Již jste se naučili, že objekt ukládá své stavy ve vlastnostech. Nicméně, programovací jazyk Java používá taktéž termín „proměnné“. Tento díl pojednává o jejich závislostech, včetně pravidel a konvencí pro pojmenovávání proměnných, o základních datových typech (primitivní typy, řetězce znaků a pole), výchozích hodnotách a literálech.
Proměnné
Jak jste se naučili v minulém díle, objekt ukládá své stavy ve vlastnostech.
int cadence = 0;
int speed = 0;
int gear = 1;
Část minulého dílu (Co je to objekt?) vás uvedla do vlastností, ale stále můžete mít několik otázek: Jaká jsou pravidla a konvence pro pojmenovávání vlastnsotí? Místo int
, jeké další datové typy se zde mohou objeit? Musí být vlastnosti inicializovány, když jsou deklarovány? Jsou vlastnostem přiřazeny výchozí hodnoty, když nejsou explicitně inicializovány? Společně v tomto díle objevím odpovědi na tyto otázky, ale předtím, než začneme, je zde několik technických záležitostí, se kterými musíte být seznámeni. V programovacím jazyce Java jsou termíny „vlastnso“ a „proměnná“ společně užívány. Toto je častý zdroj problémů u nových vývojářů než zjistí, že oba odkazují skoro na totéž.
V programovacím jazyce Java máme následující druhy proměnných:
- Proměnné instance (nestatické vlastnosti)
- Techickou mluvou, objekty ukládají své individuální stavy do „nestatických vlastnsotí&ldquo, což jsou vlastnosti definované bez klíčového slova
static
. Nestatické vlastnosti jsou taktéž známy jako proměnné instatnce, protože jejich hodnoty jsou jedinečné pro každou instanci třídy (jinými slovy, pro každý objekt); vlastnostcurrentSpeed
bicyklu je nezávislá na vlastnosticurrentSpeed
jiného. - Proměnné třídy (statické vlastnosti)
- Proměnné třídy jsou vlastnosti, u niž byl uveden modifikátor
static
; tento modifikátor říká kompilátoru, že tato vlastnost má existovat pouze jednou, nezávisle na tom, kolik objektů této třídy bylo vytvořeno. Vlastnost definující počet převodů na kole může být definována s klíčovým slovemstatic
, protože počet převodů mají všechna kola stejný. Kódstatic int numGears = 6;
tuto statickou vlastnost vytvoří. Případně může být předáno klíčové slovofinal
, aby bylo zaručeno, že se v průběhu programu počet převodů nezmění. - Lokální proměnné
- Stejně jako objekt ukládá své stavy do vlastností, metoda ukládá své dočasné stavy do lokálních proměnných. Syntaxe deklarující lokální proměnnou je naprosto stejná jako deklarace vlastnosti (např.
int count = 0;
). Neexistuje žádné klíčové slovo říkající, že proměnná je lokální; kompilátor to pozná podle umístění deklarace. Lokální proměnná se deklaruje uvnitř složených závorek, ohraničujících metodu. Z toho navíc vyplývá, že lokální proměnné může využít pouze metoda, která je definuje. Žádáná jiná část třídy k nim nemá přístup. - Parametery
- Již jste viděli příklady parametrů, ve třídě
Bicycle
a v metoděmain
„Hello World!“ aplikace. Podíváme-li se znovu na deklaraci metodymain
, tak jepublic static void main(String[] args)
. Zde je proměnnáargs
parametrem této metody. Je důležité si uvědomit, že parametry jsou kvalifikovány jako „proměnné“, ne jako „vlastnosti“. Toto se týká také jiných částí kódů přebíajících parametry (jako jsou výjimky a kontruktory, o kterých si budeme povídat dále v tutoriálu).
Je důležité si tyto pojmy zapamatovat, budeme je v tomto kontextu dále používat. Když se budeme bavit „obecně o vlastnostech“ (vyjma lokálních proměnných nebo parametrů), jednoduše řekneme „vlastnosti“. Jestliže se text bude týkat „všeho ostatního“, můžeme jednoduše říct „proměnné“. Jestliže se budeme bavit o„rozdílných tématech, přesně specifikujeme, co myslíme (statické vlastnosti, lokální proměnné, apod.). Často taktéž budeme používat termín „členská data (členové)“. Vlastnosti, metody a vložené typy jsou kolektivně nazývané členská data třídy/objektu.
Pojmenovávání
Každý programovací jazyk má svá pravidla a konvence pro pojmenovávání a ani u Javy tomu není jinak. Tato pravidla a konvece by se dala sesumarizovat asi takto:
-
U názvů proměnných záleží na velikosti písmen. Název proměnné se může skládat z libovolného platného znaku – délkově neomezená sekvence Unicode znaků a čísel – které musí začínat písmenem, znakem dolaru „
$
“ nebo znakem podtržítka „_
“. Konvencí však je, že jméno proměnné vždy začíná písmenem, nikoli dolarem či podtržítkem.
Můžete najít situace, kdy automaticky generované názvy obsahují znak dolaru, ale jména vašich proměnných by ho používat neměla. Stejná konvence platí i pro používání znaku podtržítko. Přestože je technicky možné použít na začátek proměnné znak „_
“, je tato praktika nedoporučována. Prázdné místo není povoleno. -
Následující znaky mohou být písmena, číslice, znaky dolaru nebo podtržítka. Konvence je stejná jako u prvních písmen. Když vybíráte jméno pro vaši proměnnou, používejte plná jména než kryptografické zkratky. Snažte se, co to jde, aby váš kód byl snadno čitelný. Často to vytváří kód, který sám říká, co dělá; jména vlastností
cadence
,speed
agear
, například, jsou mnohem více porozumitelné, než jejich zkratky, jako jsous
,c
ag
.
Mějte taktéž napaměti, že váš název nesmí být nějaké již existující klíčové nebo slovo rezervované programovacím jazykem. -
Jestliže se název vaší proměnné skládá pouze z jednoho slova, pište toto jméno celé malými písmeny. Jestliže obsahuje více než jedno slovo, zvětšete každé první písmeno následujícího slova. Názvy
gearRatio
acurrentGear
jsou ukázkovými příklady této konvence. Jestliže vaše vlastnost obsahuje konstantní hodnotu, jako jestatic final int NUM_GEARS = 6
, konvence je mírně jiná, zvětšete každé písmenko a slova oddělujte podtržítkem. Podle konvence se podtržítko nepoužívá kdekoli jinde.
Primitivní datové typy
Programovací jazyk Java je silně typový, což znamená, že všechny proměnné musí být prvně deklarovány, než budou moci být použity. Toto zahrnuje zadání typu a jména proměnné, jak zde můžete vidět:
int gear = 1;
Tímto říkáte, že váš program má vlastnost „gear“ uchovávájící číselná data a její výchozí hodnota je „1“. Typ proměnné definuje, jaké hodnoty může proměnná uchovávat a jaké operace mohou být nad proměnnou vykonávány.
Kromě typu int
podporuje programovací jazyk Java dalších 7 primitivních datových typů. Primitivní typ je předdefinován jazykem a je pojmenován rezervovaným klíčovým slovem. Primitivní hodnoty nesdílí své stavy s ostatními hodnotami.
Mezi osm primitivních datových typů, poskytovaných programovacím jazykem Java, patří:
-
byte: Datový typ
byte
obsahuje 8bitové dvakrát doplněné celé číslo se znaménkem. Jeho minimální hodnota je −128 a maximální 127. Datový typbyte
může být použit pro ušetření paměti ve velkých polích, kde se může ve speciálních případech hodit každý bit. Taktéž může být náhradou za typint
, kde mohou jeho limity pomoct objasnit váš kód; takto je hodnota limitována víc než údajem v dokumentaci. -
short: Datový typ
short
je 16bitové dvakrát doplněné celé číslo. Jeho minimální hodnota je −32 768 a maximální 32 767. Stejně jako u typubyte
jsou zde stejné případy použití: typshort
můžete použít k ušetření paměti při vytváření velkých polí u náročných aplikací. -
int: Datový typ
int
je 32bitové dvakrát doplněné celé číslo. Jeho minimální hodnota je −2 147 483 648 a maximální 2 147 483 647. Pro celočíselné hodnoty je tento typ tou základní volbou, pokud se nedostanete do výše popsaných situací. Tento datový typ bude dostatečně velký pro většinu čísel ve vaší aplikaci, pokud však budete potřebovat širší rozsah hodnot, použíjte místo něj typlong
. -
long: Datový typ
long
je 64bitové dvakrát doplněné celé číslo. Jeho minimální hodnota je −9 223 372 036 854 775 808 a maximální 9 223 372 036 854 775 807. Používejte tento datový typ, pokud vám nebude stačit rozsah hodnot poskytovaný datovým typemint
. -
float: Datový typ
float
je 32bitové IEEE 754 číslo s pohyblivou desetinou čárkou. Jeho rozsah hodnot je mimo toto téma, ale je specifikován v sekci 4.2.3 Java Language Specifikace. Stejně jako u typubyte
ashort
používejte typfloat
(místodouble
), pokud potřebujete uěetřit paměť ve velkých polích. Tento datový typ byste nikdy neměli používat pro přesné hodnoty, jako jsou finanční částky. Pro tento případ budete muset použít třídu java.math.BigDecimal. -
double: Datový typ
double
je 64bitové IEEE 754 číslo s pohyblyvou desetinou čárkou. Jeho rozsah hodnot je mimo toto téma, ale je specifikován v sekci 4.2.3 Java Language Specifikace. Pro desetinná čísla je tento datový typ tou základní volbou. Stejně jako typfloat
sedouble
nehodí pro přesné hodnoty, jako jsou finanční částky. -
boolean: Datový typ
boolean
má povoleny pouze 2 hodnoty:true
afalse
. Používejte tento datový typ, abyste specifikovali, zda je podmínka pravdivá (true) nebo nepravdivá (false). Tento datový typ obsahuje 1 bit informací, ale jeho velikost není přesně definována. -
char: Datový typ
char
je jednoduchý 16bitový Unicode znak. Jeho minimálni hodnou je'u0000'
(nebo 0) a maximální'uffff'
(nebo 65 535).
Kromě 8 primitivních datových typů nabízí programovací jazyk Java speciální podporu pro řetězce znaků, a to přes třídu java.lang.String. Zadáním vašeho řetězce do dvojitých uvozovek se automaticky vytvoří objekt třídy String
; například, String mujString = "toto je řetězec";
.
Objekty String
jsou neměnné, což znamená, že jakmile jsou jednou vytvořeny, jejich hodnoty se nemohou změnit. Třída String
není technicky primitivním datovým typem, ale s ohledem na speciální podporu, kterou dostává od jazyka, budete si možná myslet, že primitivním typem je. O třídě String
si více řekneme v dalších dílech.
Výchozí hodnoty
Není vždy nezbytně nutné přiřadit hodnotu vlastnosti hned při deklaraci. Vlastnosti, které byly deklarovány a neinicializovány, dostanou kompilátorem výchozí hodnotu. Obecně řečeno, do vlasntosti bude uložena buďto nula nebo null
, záleží na datovém typu. Avšak nechat to vše závislé na výchozích hodnotách je velmi špatný styl programování.
Následující tabulka ukazuje výchozí hodnoty pro výše uvedené datové typy.
Datový typ | Výchozí hodnota (pro vlasntosti) |
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0f |
double | 0.0d |
char | 'u0000' |
String | null |
Jakýkoli objekt | null |
boolen | false |
Lokální proměnné jsou mírně odlišné; kompilátor nikdy nepřiřadí výchozí hodnotu neinicializované lokální proměnné. Jesltliže nemůžete inicializovat proměnnou při její deklaraci, musíte zajistit, že tuto hodnotu proměnné přiřadíte dříve, než se pokusíte proměnnou použít. Přístup k neinicializované lokální proměnné vyústí v chybu při kompilaci.
Literály
Možná jste si všimli, že když jsme inicializovali hodnotu primitivního datového typu, nepoužili jsme operátor new
. Primitivní typy jsou speciální datové typy zabudované do jazkya; nejedná se o objekty třídy. Literál je reprezentace fixní hodnoty ve zdrojovém kódu; literály jsou přímou reprezentací bez dalších výpočtů. Jak je ukázáno níže, je možno uložit literál do proměnné primitivního datového typu:
boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;
Hodnoty celočíselných datových typů (byte
, short
, int
a long
) mohou být zapsány pomocí desítkové, osmičkové nebo šestnáctkové soustavy. Desítkovou soustavu používáte každý den;
je založena na 10 číslicích (od 0 do 9). Osmičková sooustava obsahuje 8 čísel (od 0 do 7) a konečně šestnáctková (hexadecimální) je založena na číslech od 0 do 9 a navíc písmenech A až F. Dá se říct, že při běžném programování budete používat pouze desítkovou soustavu. Nicméně, pokud budete potřebovat osmičkovou nebo šestnáctkovou soustavu, následující příklad ukazuje správnou syntaxi. Prefix 0
značí osmičkovou, zatímco 0x
značí šestnáctkovou.
int decVal = 26; // číslo 26 v desítkové
int octVal = 032; // číslo 26 v osmičkové
int hexVal = 0x1a; // číslo 26 v šestnáctkové
Typy s pohyblivou desetinnou čárkou (float
a double
) mohou být inicializovány výrazem s E nebo e (pro vědecký zápis), F nebo f (32-bit float literál) a D nebo d (64-bit double literál; tento je výchozí a podle konvence se vynechává).
double d1 = 123.4;
double d2 = 1.234e2; // vědekcký zápis
float f1 = 123.4f;
Literály typů char
a String
mohou obsahovat jakékoli Unicode (UTF-16) znaky. Jestliže to vaše prostředí umožňuje, můžete znaky zapisovat přímo. Můžete použít tzv. „Unicode escape“, jako je např. 'u0108'
(velké C s circumflexem) nebo "Su00ED seu00F1or"
(Sí señor ve španělštině). Vždy používejte 'jednoduché uvozovky' pro char
literály a "dvojité uvozovky" pro String
literály. Unicode escape sekvence mohou být použity kdekoli v programu (jako jsou např. názvy vlastností), ne pouze v char
nebo String
literálech.
Programovací jazyk Java taktéž podporuje několik speciálních escape sekvencí pro char
a String
literály: b
(backspace), t
(tabulátor), n
(nový řádek), f
(form feed), r
(návrat vozíku), "
(dvojité uvozovky), '
(jednoduché uvozovky) a \
(zpětné lomítko).
Taktéž existuje speciální literál null
, který může být přiřazen proměnné libovolného referenčního typu. null
může být přiřazen libovolné proměnné kromě těch, které jsou primitivního typu. Je toho málo, co můžete s hodnotou null
dělat kromě testování toho, zda je nastavena. Proto je často null
používán k indikaci, že je nějaký objekt nedostupný.
Konečně, je zde speciální druh literálu nazývaný literál třídy a zapisovaný názvem typu s přidáním .class
; například String.class
. Tento zápis reprezentuje objekt třídy Class
, která obsahuje informace o typu.
Pole
Objekt pole je kontejner, který ukládá předem pevně daný počet položek stejného typu. Délka (počet prvků) pole je určena, když se pole vytváří. Po jeho vytvoření je jeho délka neměnitelná. Již jste viděli pole v akci, a to v metodě main
„Hello World!“ aplikace. Tato sekce popisuje pole do většího detailu.
Každá položka v poli se nazývá element (prvek) a každý prvek je dostupný skrz jeho číselný index. Jak je ukázáno na ilustraci výše, začíná číslování na 0, devátý element je dostupný pod indexem 8.
Následujcí program ArrayDemo
vytvoří pole celočíselných hodnot, nějaké do něj vloží a vytiskne je.
class ArrayDemo {
public static void main(String[] args) {
int[] nejakePole; // deklaruje pole celých čísel
nejakePole = new int[10]; // alokuje paměť pro 10 elementů
nejakePole[0] = 100; // inicializuje první element
nejakePole[1] = 200; // inicializuje druhý element
nejakePole[2] = 300; // atd.
nejakePole[3] = 400;
nejakePole[4] = 500;
nejakePole[5] = 600;
nejakePole[6] = 700;
nejakePole[7] = 800;
nejakePole[8] = 900;
nejakePole[9] = 1000;
System.out.println("Element s indexem 0: " + nejakePole[0]);
System.out.println("Element s indexem 1: " + nejakePole[1]);
System.out.println("Element s indexem 2: " + nejakePole[2]);
System.out.println("Element s indexem 3: " + nejakePole[3]);
System.out.println("Element s indexem 4: " + nejakePole[4]);
System.out.println("Element s indexem 5: " + nejakePole[5]);
System.out.println("Element s indexem 6: " + nejakePole[6]);
System.out.println("Element s indexem 7: " + nejakePole[7]);
System.out.println("Element s indexem 8: " + nejakePole[8]);
System.out.println("Element s indexem 9: " + nejakePole[9]);
}
}
A zde je výstup tohoto programu:
Element s indexem 0: 100
Element s indexem 1: 200
Element s indexem 2: 300
Element s indexem 3: 400
Element s indexem 4: 500
Element s indexem 5: 600
Element s indexem 6: 700
Element s indexem 7: 800
Element s indexem 8: 900
Element s indexem 9: 1000
V reálné situaci byste nejspíše použili jednu z dostupných smyček pro iteraci přes každý prvek pole než vypsisování každého řádku zvlášť, jak je ukázáno výše. Nicméně, tento příklad jednoduše ilustruje syntaxi použití polí. Více se o různých smyčkách (for
, while
a do-while
) naučíte v 6. dílu seriálu.
Deklarování proměnné pro pole
Výše uvedený program deklaruje proměnnou pro pole (nejakePole
) následujícím řádkem kódu:
int[] nejakePole; // deklaruje pole celých čísel
Stejně jako deklarace jakékoliv jiné proměnné, skládá se deklarace pole ze dvou částí: typ pole a název pole. Typ pole je zapsán jako type[]
, kde type je datový typ uchováváných hodnot; hranaté závorky jsou speciální zápis, který říká, že proměnná je pole. Velikost pole není součástí typu (to je důvod, proč jsou závorky prázdné). Název pole může být cokoliv, co splňuje pravidla a konvence pro pojmenovávání proměnných, o kterých jsme mluvili dříve v článku. Stejně jako deklarace proměnných jiného typu, deklarace nevytvoří pole –
jednoduše kompilátoru říká, že proměnná bude obsahovat pole hodnot určitého typu.
Stejně můžete deklarovat pole jiných typů:
byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;
Taktéž můžete umístit hranaté závorky za název pole:
float anArrayOfFloats[]; // toto forma není doporučována
Nicméně, konvence zavrhuje tento typ zápisu; hranaté závroky definují typ proměnné, a proto by měly být uvedeny spolu s typem hodnot.
Vytvoření, inicializace a přístup k poli
Jednou z cest k vytvoření pole je operátor new
. Následující program ArrayDemo
alokuje pamět pro 10 celočíselných hodnot a uloží toto pole do proměnné nejakePole
.
nejakePole = new int[10]; // alokuje paměť pro 10 elementů
Kdyby tento příkaz chyběl, kompilátor by vydal tuto hlášku a kompilace by selhala:
ArrayDemo.java:4: Variable anArray may not have been initialized.
Následujích několik řádek toto pole inicializuje:
nejakePole[0] = 100; // inicializuje první element
nejakePole[1] = 200; // inicializuje druhý element
nejakePole[2] = 300; // atd.
Ke každém elementu v poli je přistupováno pomocí indexů:
System.out.println("Element s indexem 0: " + nejakePole[0]);
System.out.println("Element s indexem 1: " + nejakePole[1]);
System.out.println("Element s indexem 2: " + nejakePole[2]);
Kromě tohoto způsobu můžete vytvořit a inicializovat pole následujícím zkráceným zápisem:
int[] nejakePole = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
Zde je délka pole odvozena od počtu hodnot mezi {
a }
.
Můžete taktéž vytvářet pole polí (jsou taktéž známá jako vícerozměrná pole) použitím dvou nebo více dvojic hranatých závorek, jak např. String[][] jmena
. Poté se musí ke každému elementu přistupovat s odpovídajícím počtem indexů.
V programovacím jazyce Java jsou vícerozměrná pole jednoduše pole obsahující další pole. Toto je rozdíl oproti polím v jazycích C nebo Fortran. Následkem této vlastnosti jazyka je, že vícerozměrná pole nemusí mít stjenou délku u všech členů rozměru, jak ukazuje následující příklad:
class MultiDimArrayDemo {
public static void main(String[] args) {
String[][] jmena = {{"Mr. ", "Mrs. ", "Ms. "},
{"Smith", "Jones"}};
System.out.println(jmena[0][0] + jmena[1][0]); //Mr. Smith
System.out.println(jmena[0][2] + jmena[1][1]); //Ms. Jones
}
}
Tento program vypíše následující řádky:
Mr. Smith
Ms. Jones
Můžete také použít zabudovanou vlastnost length
k zjištění velikosti pole.
System.out.println(nejakePole.length);
vypíše délku pole na standardní výstup.
Kopírování polí
Třída System
obsahuje metodu arraycopy
, pomocí které můžete efektivně kopírovat data z jednoho pole do druhého:
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
Dva parametry Object
specifikují pole, ze kterého se bude kopírovat, a pole, do kterého se bude kopírovat. Tři int
specifikují startovní pozici ve zdrojovém poli, startovní pozici v cílovém poli a počet elementů, které se zkopírují.
Násedující program ArrayCopyDemo
deklaruje pole elementů typu char
hláskující slovo „decaffeinated“. Používá metodu arraycopy
ke zkopírování části jednoho pole do druhého:
class ArrayCopyDemo {
public static void main(String[] args) {
char[] kopirovatZ = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd' };
char[] kopirovatDo = new char[7];
System.arraycopy(kopirovatZ, 2, kopirovatDo, 0, 7);
System.out.println(new String(kopirovatDo));
}
}
Výpis programu:
caffein
V příštím díle
V příštím díle se zaměříme na operátory.