Algoritmické konstrukce Rudolf Pecinovský rudolf@pecinovsky.cz Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Obsah s odkazy Datové typy Literály Další informace o třídách Operátory a operace Hodnotové a odkazové objektové typy Spustitelné aplikace Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Datové typy Lokální konstanty a proměnné Jednorázová deklarace více konstant či proměnných Primitivní a objektové typy Správce paměti a jeho uklízeč Obalové třídy 29–31 35–40 147–156 197–204 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Datové typy Veškerá data, s nimiž chceme v programu v Javě pracovat, musí mít předem určen svůj datový typ, který definuje, co jsou příslušná data zač Java dělí datové typy do tří skupin Typ-netyp void Primitivní datové typy – pouze 8 zástupců: boolean, byte, short, int, long, float, double, char, Objektové datové typy – vše ostatní (ve standardní knihovně Javy 6.0 je definováno přes 18 000 datových typů, z toho je 3777 veřejných) Při práci s daty musíme používat data deklarovaného typu nebo typů s ním kompatibilních Při práci s hodnotami objektových typů dostane v Javě (a obecně ve všech moderních programovacích jazycích) žadatel vždy pouze odkaz na daný objekt Atové typy Opakování Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Lokální data – konstanty a proměnné Prozatím jsme deklarovali proměnné a konstanty pouze jako atributy; svoje data mohou mít i metody Data deklarovaná uvnitř metody označujeme jako lokální data metody; patří mezi ně Parametry = lokální data deklarovaná v hlavičce metody – jejich počáteční hodnoty nastavuje volající metoda Běžná lokální data = data deklarovaná v těle metody – jejich počáteční hodnoty je třeba nastavit v těle metody U lokálních dat nefunguje automatická inicializace, musíte je vždy inicializovat sami Parametry inicializuje volající metoda Lokální proměnné a konstanty si musí metoda inicializovat sama Použití neinicializovaného lokálního data je syntaktická chyba Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Deklarace lokálních dat Data metod jsou zásadně soukromá, zvenku nepřístupná (s výjimkou nastavování počátečního hodnot parametrů) Je možno je deklarovat jako konstanty i proměnné Nesmí u nich být žádné modifikátory přístupu, z probraných je povolen pouze modifikátor final Je možno je deklarovat na kterémkoliv místě programu, kam je možno zadat příkaz Ukládají se spolu s návratovou adresou na zásobník, a proto přestávají existovat v okamžiku opuštění metody Protože se většinou jedná o pomocné proměnné => jsou i nich tolerovány i jednoznakové identifikátory Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Příklad použití lokálních dat public Strom_3c( int x, int y, int šířka, int výška, int podílŠířkyKmene, int podílVýškyKmene ) { int výškaKmene = výška / podílVýškyKmene; int výškaKoruny = výška - výškaKmene; int šířkaKmene = šířka / podílŠířkyKmene; int posunKmene = ( šířka - šířkaKmene) / 2; koruna = new Elipsa( x, y, šířka, výškaKoruny, Barva.ZELENÁ ); kmen = new Obdélník( x+posunKmene, y+výškaKoruny, šířkaKmene, výškaKmene, Barva.HNĚDÁ ); } Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Jednorázová deklarace více dat V jedné deklaraci je možno deklarovat několik konstant či proměnných současně Podmínkou je, aby všechna současně deklarovaná data měla stejné modifikátory a typ Jednotlivé deklarace v sadě pak oddělujeme čárkami public static final int MIN = 0, MAX = 10; private Barva SVIT=Barva.BÍLÁ, TMA=Barva.ČERNÁ; private static final Směr8 NAHORU = Směr8.SEVER, DOLU = Směr8.JIH, VLEVO = Směr8.ZÁPAD, VPRAVO = Směr8.VÝCHOD; Celá deklarace má společný dokumentační komentář => výhodné pouze u soukromých dat Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Opakování Obalové třídy Řada metod odmítá pracovat s hodnotami primitivních typů Aby mohly hodnoty primitivních datových typů vystupovat v programu jako instance objektových typů, je ke každému primitivnímu typu přiřazen jeho obalový objektový typ, který je objektovým obalem kolem příslušné hodnoty Primitivní Obalový boolean Boolean byte Byte char Character double Double float Float int Integer long Long short Short void Void Opakování Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Obalové třídy a Java 5.0 Java 5.0 zavedla automatickou konverzi mezi hodnotami primitivních typů a instancemi jejich obalových typů Vyžaduje-li metoda či operátor hodnotu jednoho a my mu dodáme hodnotu druhého, překladač ji automaticky převede int i = 15; Integer ii = i / 2; i = Math.abs( ii = 10 ); Nebezpečí: Snížení efektivity programu Nepříjemné důsledky plynoucí ze specifických vlastností některých obalových typů – viz např. Pecinovský: Java 5.0 – Novinky jazyka a upgrade aplikací, CP Books 2005, ISBN 80-251-0615-2 Knihu je možno stáhnout ve formátu PDF na adrese http://knihy.pecinovsky.cz/java5novinky Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Literály Literály – jejich výhody a nevýhody Literály primitivních datových typů Řetězcové literály 29–31 35–40 147–156 197–204 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Literály Literál = konstanta pojmenovaná svojí hodnotou 3, "Ahoj", 'A', true, null, … Java umožňuje zadávat literály všech primitivních typů + textové řetězce (instance třídy String) + prázdný odkaz Používání „magických hodnot“ (= literálů) uvnitř programu je považováno za nevhodné Literály snižují srozumitelnost Literály snižují modifikovatelnost Za akceptovatelné jsou považovány pouze 0, 1, "", null, true, false Za magické hodnoty jsou považována všechna čísla s výjimkou nuly a jedničky (a někdy i ty) Před použitím literálů uvnitř programu se dává přednost používání běžných pojmenovaných konstant, kterým na počátku programu přiřadím pomocí literálu hodnotu Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Logické literály a prázdný odkaz true – ANO, pravda, false – NE, nepravda Prázdný odkaz (odkaz nikam) – null Lze jej přiřadit jako hodnotu kteréhokoliv odkazu Tento odkaz lze pouze porovnat s jiným odkazem, nic jiného s ním není možno dělat Posílání zprávy instanci prostřednictvím prázdného odkazu patří mezi nejčastější chyby; systém na ně odpovídá vyhozením výjimky NullPointerException Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Celočíselné literály Celočíselné literály lze zadávat ve třech číselných soustavách; použitá soustava se pozná podle začátku čísla: 0x = šestnáctková (hexadedicmální) soustava: 0xA = 10; 0xFF = 255 0 (nula následovaná číslicemi) = osmičková (oktalová) soustava: 012 = 10; 0377 = 255 Nezačíná nulou = desítková soustava Počáteční + se psát může, ale nemusí Hodnoty typu long je třeba psát s příponou L či l 0L, 9_876_543_210L, -1L 9876543210 – syntaktická chyba, na celé číslo je moc velké Pro zadání hodnot typu byte a short je třeba použít operátoru přetypování (viz dále) byte b = (byte)0; Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
„Reálné“ literály U reálných literálů se pro určení typu používají přípony D nebo d pro čísla typu double: 1d; –3D F nebo f pro čísla typu float: 1f; –3F Při zadávání desetinné části se používá desetinná tečka Implicitním typem reálných čísel je double double d = 1.23; float f = 1.23f; //f = 1.23 je syntaktická chyba Čísla je možno zadávat buď v přímém, nebo v semilogaritmickém (vědeckém) tvaru Přímý tvar: 1.23 Semilogaritmický tvar: 1.23e2 (=1,23.102) 3e-3 (=3.10-3) Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Znakové literály Znaky, které je možno přímo zadat, se píší mezi apostrofy 'ž', 'X', '©', '±', '$', '«', 'Ξ', 'گ', '♣' Znaky je možno zadat také přímo jejich kódem ve formátu \uHHHH, kde H představuje hexadecimální číslici, nebo \OOO, kde O představuje oktalovou číslici (nepoužívat) Některé řídící znaky mají vlastní způsob zápisu označovaný jako escape sekvence \b = \u0008 = backspace – odmazání předchozího znaku \t = \u0009 = HT = horizontální tabulátor \n = \u000A = LF (line feed) – přechod na další řádek \f = \u000C = FF (form feed) – přechod na další stránku \r = \u000D = CR (carriage return) – přechod na počátek řádku \" = \u0022 = uvozovky (double quote) \' = \u0027 = apostrof (single quote) – '\'' \\ = \u005C = zpětné lomítko (backslash) Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Řetězcové literály Textové řetězce jsou instance objektového typu String String je (zatím) jediný objektový typ, který má vlastní literály Textový řetězec zadáváme jako posloupnost znaků uzavřenou mezi uvozovkami Uvnitř literálu nesmějí být řídící znaky (např. odřádkování), místo nich je třeba zadat příslušné escape sekvence "První řádek\nDruhý řádek\fDalší stránka" Znaky, které nechcete zadávat přímo (např. kvůli převodu mezi platformami) je možno zadávat kódem Místo "Přenositelná čeština" zapíšeme "P\u0159enositeln\u00E1 \u010DE\u0161tina" Místo Příliš žluťoučký kůň úpěl ďábelské ódy zapíšeme P\u0159\u00EDli\u0161 \u017Elu\u0165ou\u010Dk\u00FD k\u016F\u0148 \u00FAp\u011Bl \u010F\u00E1belsk\u00E9 \u00F3dy Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Další informace o třídách Třídní členy Inicializační blok a statický konstruktor Zavedení třídy a její inicializace Postup při vytváření instancí Spuštění celého programu Soubory JAR BlueJ a vytváření souborů JAR 61–66 183–185 473–477 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Opakování Třídy a jejich členy Dělení členů Třídní × instanční Datové (atributy) × funkční (metody) × typové (třídy a rozhraní) Instanční členy mají vždy vazbu na svoji instanci Atributy jsou umístěny v paměti přidělené jejich instanci Metody mají skrytý parametr this odkazující na jejich instanci Třídy mají skrytý atribut Vnější.this odkazující na jejich instanci Členy, které patří celé třídě označujeme modifikátorem static Specifika třídních členů Atributy jsou všemi instancemi sdíleny; o každé změně hned všechny vědí Metody je možno volat před vytvořením první instance Jako třídní členy lze použít i rozhraní (nesmějí mít atribut, takže jen třídní) Opakování Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Vytvoření instance O vytvoření zcela nové instance je třeba požádat virtuální stroj (ostatní mechanizmy pouze kopírují dříve vytvořený objekt) Ostatní mechanizmy: klonování, serializace Postup vytváření nové instance Připraví (= vyhradí a vynuluje) na haldě místo pro budoucí instanci Vloží do něj odkaz na tabulku virtuálních metod (VMT) Připraví odkaz na vytvářenou instanci (this) jako nultý parametr Vyhodnotí předávané parametry a připraví je k předání Zavolá konstruktor rodiče Prochází program a v pořadí dle zdrojového kódu Inicializuje instanční konstanty a proměnné Spouští instanční inicializační bloky Vstoupí do těla konstruktoru a provede je Vrátí žadateli (volajícímu programu) odkaz na vytvořenou instanci Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Statické a instanční členy – ukázka public class Zaměstnanec { private static int počet; private String jméno; private String příjmení; public Zaměstnanec( String jméno, String příjmení){ this.jméno = jméno; this.příjemní = příjmení; počet ++; } public static int getPočetZaměstnanců(){ return početZaměstnanců; Zaměstnanec: početZaměstnanců: 1 Zaměstnanec: početZaměstnanců: 2 Zaměstnanec: početZaměstnanců: 0 1 2 Zaměstnanec_1: jméno: Pepa příjmení: Zdepa Zaměstnanec_1: jméno: příjmení: this this Zaměstnanec_2: jméno: Jana příjmení: Vdaná Zaměstnanec_2: jméno: příjmení: ++ ++ jana: pepa: počet: 2 počet: 0 počet: int počet = Zaměstnanec.getPočetZaměstnanců(); Zaměstnanec pepa = new Zaměstnanec ( "Pepa", "Zdepa" ); Zaměstnanec jana = new Zaměstnanec ( "Jana", „Vdaná" ); počet = Zaměstnanec.getPočetZaměstnanců(); ? ® Pepa Zdepa ® Jana Vdaná ? Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Inicializační blok Na úrovni metod je možno definovat i nepojmenovaný blok příkazů Tento blok je součást konstruktoru a spouští se v rámci inicializací atributů těsně před vlastním tělem konstruktoru Nepojmenovaný inicializační blok je náhražkou konstruktoru v situacích, kde klasický konstruktor není možno použít Označíme-li nepojmenovaný blok modifikátorem static vytvoříme tak blok, který nahrazuje konstruktor třídy ® bývá označován jako statický konstruktor public class Třída { private final int[] pole = načti(); private final int součet; { for( int i=0,s=0; i < pole.length; s += pole[i++] ); součet = s; } public Třída() {} int getPrvek(int i) {return pole[i];} Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Statický inicializační blok V tomto bloku můžeme provádět akce, které je třeba vykonat před zavedením třídy do paměti Nepojmenovaný statický blok je jediné místo, kde je možno inicializovat statické konstanty (samozřejmě kromě jejich deklarace) Inicializačních bloků může být libovolné množství, definice více než jednoho bloku však není vhodná, protože znepřehledňuje program Inicializační bloky se spouštějí v okamžiku, kdy na ně při průchodu programem dojde řada => v statickém inicializačním bloku nesmíme používat data, která jsou deklarována až po něm Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Inicializace třídy Třída se zavádí do paměti, až když ji někdo potřebuje Obrací-li se někdo na třídu poprvé, tj.: Žádá po třídě hodnotu jejího dostupného atributu Volá nějakou třídní metodu Volá konstruktor virtuální stroj zjistí, že třídu ještě nemá zavedenou, a požádá zavaděč tříd (ClassLoader), aby ji zavedl Povolaná instance třídy ClassLoader: Najde binární obraz třídy (class soubor, pole bajtů, …) Vytvoří její objekt Prochází „kód“ a inicializuje třídní atributy a spouští statické inicializační bloky Předá objekt třídy virtuálnímu stroji Třídu lze vytvořit i za chodu programu, a to do binárního pole Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Správa dynamické paměti Instance objektových typů vznikají zásadně na haldě (heap), kterou spravuje správce paměti (memory manager) Aby mohl správce spravovat paměť spolehlivě a efektivně, potřebuje, aby mu do toho nikdo „nekecal“ => proto k instancím nikoho nepustí a nutí nás se k nim obracet pouze prostřednictvím příslušných odkazů Instance je držena v paměti do chvíle, dokud ji někdo potřebuje, tj. dokud si na ni někdo drží odkaz Instance, na níž se již nikdo neodkazuje, je předána uklizeči, který ji příležitostně „uklidí“ a tím uvolní její místo v paměti Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Uklízeč (garbage collector) Uklizeč (garbage collector) je program (spíš modul), který je nedílnou součástí správce paměti a je zodpovědný za odstraňování nepotřebných instancí Jeho činnost je tak klíčová, že je často vydáván za správce paměti O tom, kdy bude paměť uvolněna rozhoduje pouze uklizeč, není šance mu jakékoliv rozhodnutí vnutit Metody, které uklízeče „spouští“ (např. System.gc()), jej pouze upozorňují, že se programátor domnívá, že nyní je vhodný čas na úklid; rozhodnutí o tom, co a kdy se bude uklízet je ale zcela v kompetenci uklízeče Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Přehled operátorů podle arity Operace × příkazy Méně známé skutečnosti Operátory a operace Přehled operátorů podle arity Operace × příkazy Méně známé skutečnosti 31–37 197–204 237–241 451 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Přehled operátorů podle arity Nulární Konstanty: null true false Unární Prefixové: + - ! ++ -- Postfixové: ++ -- Binární (infixové) Aritmetické: + - * / % Porovnávací: < <= == != >= > Logické: & | && || Bitové: ~ & | ^ << >> >>> Přiřazovací: = += -= *= /= %= |= &= ^= <<= >>= >>>= Ostatní: instanceof . (kvalifikace) () (přetypování; není infixový) Ternární Podmíněný výraz: ?: Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Operace × příkazy Všechny operace provedou požadovanou činnost se svými operandy a vrátí nějakou hodnotu I přiřazení je operace; vrací přiřazovanou hodnotu Výraz je tvořen sledem operací; z výrazu uděláme příkaz tím, že za něj zapíšeme středník; do té doby je to vždy jen výraz, který může vystupovat jako operand v jiných výrazech První z následujících deklarací je syntakticky korektní (i když prasácká): int i, j = (i=3) * 3; Color c = new Elipsa().getBarva().getColor(); IGUI g = new GUI( new MojeCPU() ); Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Operátor přetypování V závorce se zadává název typu, na nějž přetypováváme, za závorkou výraz, jehož hodnotu přetypováváme Příklad: System.out.println( "Znak=" + (char)34 ); Hodnoty číselných primitivních typů je možno libovolně vzájemně přetypovat u ostatních musíme vědět, že je přetypování korektní Instance třídy implementující rozhraní je v případě potřeby automaticky přetypována na instancí daného rozhraní Víme-li, že nějaká instance je instancí dané třídy, můžeme ji na tuto třídu přetypovat public boolean equals( Object o ) { if( !(o instanceof Pozice) ) return false; Pozice p = (Pozice)o; return (this.x == p.x) && (this.y == p.y); } Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Převody mezi primitivními typy Převody z „menšího“ typu na „větší“ je ochoten dělat překladač byte ® short ® int ® long ® float ® double char ® int Pro převody z „většího“ typu na „menší“ je třeba použít operátor přetypování Při převodu z reálných typů na celočíselné se useknou desetinná místa Při převodu double ® float se pouze ztratí platné číslice Při převodu mezi celočíselnými typy se ztratí významnější bity byte b = (byte) 300; //b = 300 – 256 = 44 Při převodu velkých reálných čísel na celá se dosadí největší celé číslo int i = (int) 1e12; //i = 2147483647 Při převodu int/long ® float a long ® double se ztrácejí platné číslice: Platných číslic: int 9; long 18; float 6; double 15 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Znaky a celá čísla Znaky jsou uloženy jako dvoubajtové kódy (případně jako posloupnost dvou dvoubajtových kódů) Rozdílná podstata znaků a čísel se projeví až ve chvíli, kdy se daná hodnota tiskne Do znakových dat (char) lze libovolně vkládat celá čísla (int) a do celočíselných dat lze libovolně vkládat znaky char c; //Následující přiřazení jsou c = 9; //navzájem ekvivalentní c = (char)9; c = '\t'; c = '\u0009' Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Méně známé skutečnosti Aritmetické operace Typ výsledku záleží na typu operandů; „větší“ operand přehlasuje „menší“ Operace nad hodnotami typů short a byte vrací výsledek typu int byte b1=1, b2=2, b3=(byte)(b1 + b2); U binárních se levý operand vyhodnocuje vždy první int i = 2, j = (i=3) * i; //j = 9 Operátory && a || aplikují zrychlené vyhodnocení, tj. znají-li po vyhodnocení levého operandu výsledek, pravý již nevyhodnocují; operátory & a | vyhodnotí vždy oba operandy Test (n & 1) vrací informaci o tom, je-li n liché Bitový posun <<, resp. >> je rychlejší verzí násobení, resp. dělení mocninou dvou Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Vlastnosti některých operací Operátory inkrementace a dekrementace ++ a -- Přičtou, resp. odečtou od svého argumentu jedničku To, jestli operátor vrátí hodnotu před nebo po provedení operace záleží na umístění operátoru vůči jeho operandu Ukázky použití: viz např. modrá učebnice str. 201 Ternární operátor (podmíněný výraz) V závislosti na výsledku vyhodnocení prvního operandu vrátí hodnotu druhého nebo třetího operandu Ukázky použití: viz např. modrá učebnice 451 int abs = (x > 0) ? x : -x; Dělní nulou U celých čísel vyhazuje chybu ArithmeticException: / by zero U reálných čísel vrací hodnotu Double.POSITIVE_INFINITY, resp. Double.NEGATIVE_INFINITY Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Složené operátory přiřazení Slučují operaci prováděnou s proměnnou, do níž se přiřazuje výsledek operace Šetří opakované psaní levého operandu x op= y ≡ x = x op (y) //Závorka v předchozím výrazu je důležitá int i=1, j=10, k=100; i *= j + k; // i = 1 * (10 + 100) //NE i = 1 * 10 + 100 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Sčítání textových řetězců Třída String je (zatím) jediný objektový typ, který má vlastní přetížený operátor Je-li kterýmkoliv z operandů operátoru + textový řetězec (= instance třídy String), převede se i druhý operand na textový řetězec a výsledkem je řetězec vzniklý jejich sloučením "Ahoj" + "Franto" ® "AhojFranto" Výraz "" + x může sloužit jako převod či přetypování libovolné hodnoty x na textový řetězec Pozor na typy operandů v „součtu“ Vyhodnocuje se zleva doprava, vždy se dva sečtou a výsledek použije Výraz (10 + '\n' + " kusů") má hodnotu "20 kusů" Výraz ("Kusů: " + 10 + '\n') má hodnotu "Kusů: 10\n" Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Hodnotové a odkazové objektové typy Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Primitivní a objektové typy Java pro zvýšení efektivnosti dělí datové typy na: Primitivní někdo je označuje jako hodnotové, protože se u nich pracuje přímo s hodnotou daného objektu (číslo, znak, logická hodnota) Objektové někdo je označuje za referenční, protože se u nich pracuje pouze s odkazem („referencí“) na objekt Dělení na hodnotové a odkazové není terminologicky vhodné protože objektové typy dále dělíme na hodnotové a odkazové Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Trocha češtiny Někteří autoři označují odkazové typy jako referenční Z jazykového hlediska je to stejná chyba, jako překládat control (řídit) kontrolovat (check) Reference (česky) = zpráva, dobrozdání, doporučení, posudek Viz Akademický slovník cizích slov, ISBN 80-200-0524-2, str. 652 Reference (anglicky) = zmínka, narážka, odkaz, vztah, … Viz Velký anglicko-český slovník, nakl. ČSAV 21-055-85, str. 1181 Obdobně referovat odkazovat Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Důsledek odkazové podstaty objektů Ukazují-li dva odkazy na jeden objekt, pak změna stavu objektu vyvolaná zasláním zprávy prostřednictvím jednoho odkazu je současně změnou stavu objektu odkazovaného druhým odkazem public int coVrátímObj() { Obdélník o1, o2; o1 = new Obdélník(); o2 = o1; o1.setŠířka( 200 ); return o2.getŠírka(); } public int coVrátímPrim() { int i1, i2; i1 = 19; i2 = i1; i1 = 2 * i1; return i2; } Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Šířka obdélníků graficky x = 0 y = 0 šířka = 100 výška = 50 i1: 19 i1: ??? i1: 38 19 38 19 x = 0 y = 0 šířka = 200 výška = 50 o2: 200 i2: 19 i2: ??? 19 public int coVrátímO() { Obdélník o1, o2; o1 = new Obdélník(); o2 = o1; o1.setŠířka( 200 ); return o2.getŠírka(); } public int coVrátímP() { int i1, i2; i1 = 19; i2 = i1; i1 = 2 * i1; return i2; } Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Dělení objektových datových typů Odkazové datové typy (reference data types) Neuvažujeme o hodnotách, objekt představuje sám sebe, nemá smysl hovořit o ekvivalenci dvou různých objektů Příklady Geometrické tvary Vlákna Hodnotové datové typy (value data types) Objekt zastupuje nějakou hodnotu Objekty se stejnou hodnotou se mohou vzájemně zastoupit => má smysl hovořit o jejich ekvivalenci Obalové typy, zlomky, velká čísla a další matematické objekty Barvy, časy, data Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Dělení hodnotových objektů Proměnné (mutable) Hodnota jejich atributů se může v průběhu života měnit – viz příklad z počátku přednášky Nesmějí se používat v některých situacích Neměnné (immutable) Hodnotu, která jim byla přiřazena „při narození“ zastupují až do své „smrti“ Chovají se obdobně jako hodnoty primitivních typů a také je s nimi možno obdobně zacházet Metody, které mají měnit hodnotu objektu, musejí vracet jiný objekt s touto změněnou hodnotou Hodnotové typy bychom měli vždy definovat jako neměnné Proměnné hodnotové typy jsou pro program nebezpečné, a proto je používáme pouze výjimečně, máme-li pro jejich použití opravdu pádné důvody Objektový Odkazový Hodnotový Proměnný Neměnný Primitivní Typ Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Porovnávání objektů Při porovnávání objektů zjišťuje operátor == pouze to, jedná-li se o shodné instance Požadujeme-li test shody hodnot, používáme volání metody equals(Object), která zjišťuje rovnost hodnot Všechny třídy dostanou tuto metodu nadělenou od systému, její implicitní verze vrací totéž, co operátor == U odkazových objektových typů to vyhovuje, u hodnotových typů musíme definovat jejich vlastní verzi Ruku v ruce s metodou equals(Object) by měla jít i definice metody hashCode(), která je s ní velmi úzce svázána Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Metoda equals(Object) public class Pozice { public final int x, y; //... Konstruktor a jiné metody vynechávám public boolean equals( Object o ) { return (o instanceof Pozice) && (x == ((Pozice) o).x) && (y == ((Pozice) o).y); } Zdánlivě obrácený směr šipky je důsledkem toho, že implikace je ekvivalentní s operaci "menší nebo rovno" Kontrakt Reflexivní: a.equals(a) == true Symetrická: a.equals(b) == b.equals(a) Tranzitivní: a.equals(b) & b.equals(c) <= a.equals(c) Konzistentní (co platí teď, musí platit pořád – proto musí být neměnné) Nenullové: a.equals(null) == false Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Doporučení pro tvorbu neměnných objektů Používání proměnných hodnotových objektů výrazně snižuje robustnost a bezpečnost programů Neměnné musí zůstávat jen atributy, jejichž hodnoty používají metody equals(Object) a hashCode() Atributy neovlivňující výsledky těchto metod se mohou měnit, protože na nich hodnota instance nezávisí Příklad: Atributy počítající počet použití dané instance, počet volání některé metody atd. V definovaných třídách by měly všechny „změnové metody“ vytvářet nové instance Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Sčítání textových řetězců podruhé Třída String definuje hodnotový neměnný typ => sloučením řetězců vznikne vždy nový objekt public static void testShodyŘetězců() { String sa = "Ahoj", sb = sa; boolean rovno, equals; sa += "!"; // sa="Ahoj!" rovno = (sa == sb+"!"); // false equals = sa.equal(sb+"!"); // true Systém.out.println( "Shoda instancí: " + rovno + "\nShoda hodnot: " + equals ); } Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Příklad: Zlomek public class Zlomek { private final int c; //čitatel private final int j; //jmenovatel; public Zlomek plus(Zlomek z) { //this. return new Zlomek( this.c * z.j + z.c * j, this.j * z.j ); } public Zlomek krát(Zlomek z) { return new Zlomek( c * z.c, j * z.j ); public boolean equals(Object o) { return (o.instanceof Zlomek)) && (c == ((Zlomek) o).c) && (j == ((Zlomek) o).j); Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Spuštění celého programu Soubory JAR BlueJ a vytváření souborů JAR Spustitelné aplikace Spuštění celého programu Soubory JAR BlueJ a vytváření souborů JAR 61–66 183–185 473–477 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Metoda main(String[]) Nespouštíme-li program pod vývojovým prostředím, musíme virtuálnímu stroji prozradit, kde má s vykonáváním programu začít Oznámíme mu startovní třídu programu; ta musí obsahovat metodu (na jméně parametru nezáleží, jen na jeho typu): public static void main( String[] args ) nebo public static void main( String... args ) Tuto metodu virtuální stroj spustí BlueJ nabízí vytvoření třídy s předdefinovanou metodou main Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
BlueJ a metoda main BlueJ umí spustit i aplikaci neobsahující hlavní třídu s metodou main(String[]) Hlavní třídu s touto metodou potřebujeme pouze chceme-li danou aplikaci spouštět přímo jako jiné aplikace v daném operačním systému Po žádosti o vytvoření hlavní třídy se vytvoří třída obsahující pouze metodu main(String[]) Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Šablona hlavní třídy aplikace /************************************************************** * Třída Hlavní slouží ke spouštění aplikace ... * * @author jméno autora * @version 0.00.000 */ public class Hlavní { /********************************************************** * Metoda, prostřednictvím níž se spouští celá aplikace. * @param args Parametry načtené z příkazového řádku public static void main( String [] args ) /*# Sem vložte kód, kterým se bude aplikace spouštět.*/ } Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Aplikace v archivech JAR Kompletní aplikace se v Javě balí do souborů s příponou JAR (JAR = Java ARchive) Soubor JAR je klasický ZIP soubor doplněný o složku META-INF s textovým souborem MANIFEST.MF s informacemi o aplikaci V programu Total Commander lze do souboru JAR vstoupit klávesovou zkratkou PgDown Povinné řádky v souboru MANIFEST.MF: Manifest-Version: 1.0 – verze manifestu je stále 1.0 Created-By: 1.6.0_24 (Sun Microsystems Inc.) – Informace o verzi a dodavateli použité verze Javy Main-Class: Xyz – kde Xyz je úplný název hlavní třídy aplikace (nejedná-li se o spustitelnou aplikaci, ale jenom o knihovnu, řádek s uvedením hlavní třídy být uveden nemusí) Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
BlueJ a vytváření aplikací BlueJ umí na požádání zabalit aplikaci do souboru JAR Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Spouštění aplikací v souborech JAR Většina operačních systémů umožňuje tyto aplikace spouštět obdobně jako klasické aplikace Druhou možností je spouštění z příkazového řádku Konzolový řežim: java –jar soubor parametry Spustí se aplikace spolu s konzolovým oknem, do nějž se vypisují texty pro standardní a chybový výstup Okenní režim: javaw –jar soubor parametry Otevře se pouze okno aplikace bez konzoly, standardní i chybový výstup jdou standardně „do kanálu“ Předpokládá se, že program vše vypisuje do oken Ve Windows se při standardní instalaci Javy automaticky sdruží soubory JAR s okenním voláním Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Děkuji za pozornost Rudolf Pecinovský http://vyuka.pecinovsky.cz/vse mail: rudolf@pecinovsky.cz ICQ: 158 156 600 Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Pgm Používaná písma a objekty Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Demi) Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Medium) Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Cond) Příliš žluťoučký kůň úpěl ďábelské ódy (Heavy) Příliš žluťoučký kůň úpěl ďábelské ódy (Franklin Gothic Book) Příliš žluťoučký kůň úpěl ďábelské ódy (Comic Sans MS) Příliš žluťoučký kůň úpěl ďábelské ódy (Consolas) Příliš žluťoučký kůň úpěl ďábelské ódy Příliš žluťoučký kůň úpěl ďábelské ódy Opakování Program Keyword Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce
Konvence syntaktických definic Syntaktická definice = pravidla zápisu konstrukce jazyka Název – Název definované součásti součást – Název součásti definované jinde program – Text, který se přímo použije (opíše) [ ] – Obsah hranatých závorek je volitelný { | } – Výběr z několika možností oddělených | – Druhou možností je psaní možností pod sebe … – Předchozí položka se může opakovat ¶ – Definice pokračuje na dalším řádku kde bude navíc odsazená Příklad: Identifikátor: písmeno [ { písmeno | číslice } ] … Číslice: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 Originál: P02_Prvni_kod.ppt#23. Konvence syntaktických definic Copyright © 2009, Rudolf Pecinovský VŠE – 04. Algoritmické konstrukce