7 Formátovaný výstup, třídy, objekty, pole, chyby v programech Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost formátovanému výstupu, úvodu do tříd a objektů a polím.
Doba nutná k nastudování
2 – 2,5 hodiny
7.1 Formátovaný výstup V bloku 3 jsme si uvedli základní příkaz pro výpis zadaného textu do konzole. Nyní se můžeme podívat na možnosti formátování výstupu do konzole v jazyce Java (např. když chceme vypsat hodnoty s určitou přesností, s určitým zarovnáním apod.). Další možnosti pro výpis textu do konzole jsou následující: System.out.print("text"); Výpis textu, kurzor zůstává na stejném řádku System.out.println("text"); Výpis textu s odřádkováním, kurzor se přesouvá na další řádek System.out.printf(format, polozky); Výpis s možností formátování, kde o
format – text se znaky pro formátování textu. Obecný zápis formátu je následující: %[modifikator][sirka][.presnost]konverze Konverze je povinný parametr a pro různé formy výpisu používáme různé parametry: celé číslo – d, o, x (dekadicky, oktalově, hexa) desetinný zápis – f, e – vědecký zápis s exponentem šířka – počet sázených míst, zarovnání vpravo .přesnost – počet desetinných míst modifikátor – další vlastnosti, např. znak + (znaménko), znak - (zarovnání vlevo), znak 0 (doplnění čísla zleva nulami)
KST/IZAPR - Základy programování
blok 7, strana 1 (10)
Michael Bažant
%n- přechod na další řádek
o
polozky – hodnoty pro dosazení. Nejčastěji se jedná o proměnné, jejichž hodnotu chceme vypsat do konzole.
Příklady použit formátovaného výstupu: System.out.printf("Cislo System.out.printf("Cislo System.out.printf("Cislo System.out.printf("Cislo System.out.printf("Cislo
Pi = Pi = Pi = = %d = %d
%6.3f %n", Math.PI); %8.3f %n", Math.PI); %6.5e %n", Math.PI); %n", cislo); %n", -33);
7.2 Třídy, objekty - úvod V bloku 4 jsme si představili dva základní druhy datových typů v jazyce Java – primitivní a referenční a řekli jsme si, že proměnné referenčního datového typu odkazují na objekty. V této kapitole se seznámíme se základy tříd a objektů (abychom se mohli seznámit s poli) a v dalším bloku se podíváme na bližší informace o objektech. Doposud jsme pracovali jen s primitivními datovými typy, v této kapitole se blíže podíváme na referenční datový typ, vytváření tříd a objektů a nejprve se seznámíme s třídami, které jsou pro práci s referenčními datovými typy základním prvkem. Pro připomenutí - referenční datový typ odkazuje na objekt v paměti (nepracujeme přímo s pamětí, proto nepoužíváme označení ukazatele). Nejprve začneme definicí tříd – definic je celá řada, ale nejvýstižnější je asi tato: třída je popisem strukturovaného datového typu, obsahuje datové prvky potřebné pro objekt (stav objektu) a množinu metod pro práci s datovými prvky (mění stav objektu). Další z definic by mohla vypadat následovně: třída je programová jednotka tvořená množinou identifikátorů, které mají třídou definovaný význam a asi nejvíce obecnou definicí je ta, kdy je třída považována za zdroj metod popisujících řešení problému rozkladem na podproblémy. Všechny tyto definice jsou v pořádku a vzájemně se doplňují, pro nás v tuto chvíli bude nejdůležitější skutečnost, že třídy vytváříme pomocí zápisu zdrojového kódu (třída obsahuje kód napsaný programátorem). Abychom si hned udělali jasno mezi pojmy třída a objekt, tak si nyní vysvětlíme pojem objekt. Objekty jsou vytvářené při běhu programu dle předpisu, kterým je třída a proto se o objektech bavíme jako o instancích třídy, neboť na základě jedné třídy může být vytvořeno mnoho objektů. Z tohoto pohledu je třída předpis (šablona) pro vytváření objektů a JVM na základě definovaných tříd vytváří při běhu programu objekty (instance).
KST/IZAPR - Základy programování
blok 7, strana 2 (10)
Michael Bažant
Třída je popis dat a chování, kterými disponuje každý objekt. Příklad: Třída: Student Objekty (reps. ref. prom. na objekty): studentNovak, studentNovy... Pro vysvětlení postupu při vytváření objektů použije následující obrázek (viz Obrázek 1). Deklarace referenční proměnné je v zásadě stejná jako u deklarace proměnné primitivního datového typu, jen s tím rozdílem že nepoužijeme primitivní datový typ, ale název třídy. P-hodnotou výrazu je potom operátor new, kterým vytváříme nové objekty a název třídy s kulatými závorkami (této části říkáme konstruktor třídy).
Obrázek 1: Postup při vytváření objektu
Nyní se podíváme na obecnou syntaxi třídy a také na konkrétní třídu s názvem Student, která obsahuje jeden atribut v podobě známky studenta z předmětu programování a jednu metodu pro výpis známky z předmětu programování do konzole.
Obrázek 2: Obecná syntaxe třídy
KST/IZAPR - Základy programování
blok 7, strana 3 (10)
Michael Bažant
Obrázek 3: Příklad třídy Student
7.3 Třídy – atributy Po představení syntaxe třídy si představíme bližší informace o atributech třídy. Opět nejprve v obecné formě (viz Obrázek 4) a potom také na příkladu třídy Obdelnik (viz Obrázek 5), která bude disponovat atributy délka, šířka, zda je zobrazen a také označením daného obdélníka.
Obrázek 4: Obecný zápis atributů tříd
Obrázek 5: Atributy třídy Obdelnik
V rámci třídy k atributům přistupuje pomocí tečkové notace. Příklad: obdelnik1.delka = 5;
7.4 Třídy – metody Pomocí metod tříd popisujeme činnosti, které bude daný objekt umět vykonat. Opět se nejprve podíváme na obecný zápis metod (viz ) a poté na konkrétní příklad (viz ). KST/IZAPR - Základy programování
blok 7, strana 4 (10)
Michael Bažant
Obrázek 6: Obecný zápis metod tříd
Obrázek 7: Metoda třídy Student
7.5 Jednorozměrná pole V jazyce Java jsou všechny pole objekty (je jedno zda se jedná o pole, které obsahuje prvky primitivního datového typu nebo prvky referenčního datového typu), což je také důvodem proč této kapitole předcházely alespoň základní informace o třídách a objektech. Pokud chceme deklarovat proměnnou, která bude odkazovat na objekt typu pole, je nutné použít primární výrazový operátor [], který se může nacházet jak před názvem proměnné, tak za ním (dle konvencí před názvem proměnné). Tento operátor je také používán pro přístup k prvkům pole. Způsob deklarace proměnné typu jednorozměrné pole můžeme demonstrovat na následujících příkladech. Zde je nutné upozornit na tu skutečnost, že samotnou deklarací těchto proměnných nedochází k vytváření žádných objektů typu pole, ale dochází opravdu pouze k deklaraci proměnné (tzn. pouze k alokaci místa pro referenční proměnnou, nikoliv pro samotný objekt typu pole a tudíž máme k dispozici proměnnou, která má schopnost odkazovat na objekt typu jednorozměrné pole, ale ještě na žádný neodkazuje). Příklady: double[] poleRealnychCisel; //prvky pole typu //double double poleRealnychCisel[];//nedoporucuje se ale //syntakticky v poradku char[] poleZnaku; //prvky pole typu char Student[] poleStudentu; //pole referenci na //objekty typu Student
KST/IZAPR - Základy programování
blok 7, strana 5 (10)
Michael Bažant
Samotný objekt typu jednorozměrné pole vytvoříme (stejně jako i ostatní objekty) pomocí operátoru new nebo pomocí vyjmenování konkrétních hodnot, které má pole obsahovat (viz další text této kapitoly). Nejprve tedy ke způsobu vytváření pole pomocí operátoru new – kdy po tomto operátoru následuje název datového typu, jehož budou jednotlivé prvky pole a do hranatých závorek zapíšeme kapacitu pole (počet prvků) – viz následující příklady. Počet prvků pole musí být stanoven při vytváření objektu typu pole a tento počet nelze již dále měnit. Příklady na vytváření jednorozměrného pole: double[] pole1 = new double[10]; datovyTyp[] pole2 = new datovyTyp[pocetPrvku]; Druhou možností pro vytvoření pole je, že při vytváření objektu pole inicializujeme s použitím zkrácené syntaxe s využitím symbolů {}: int[] pole = {2, 3, 1, 5, 10}; Indexování prvků v poli v jazyce Java začíná vždy od nuly, tzn. že pole[0] odkazuje na první prvek pole a index posledního prvku v poli je roven kapacitě pole sníženému o hodnotu jedna – pro přechozí příklad pole1 bude mít poslední prvek index pole[9]. Ukázka pole s deseti prvky viz Obrázek 8.
Obrázek 8: Prvky v jednorozměrném poli prim. datového typu
Pro zjištění počtu prvků pole používáme atribut objektu s názvem length – viz následující příklad. double[] pole = new double[10]; System.out.println(“Pocet prvku pole = ” + pole.length);
KST/IZAPR - Základy programování
blok 7, strana 6 (10)
Michael Bažant
Standardní hodnoty (pokud neuvedeme při vytváření objektu hodnoty jiné) prvků pole jsou pro: číselné primitivní datové typy – 0 datový typ char – ’\u0000’ primitivní datový typ boolean – false Při vytváření kopií polí je nutné mít na paměti, že pracujeme s referenčními proměnnými. Tuto skutečnost můžeme demonstrovat na příkladu kopírování polí, kdy nestačí použít operátor přiřazení – viz následující příklad. double[] pole1 = new double[10]; double[] pole2 = new double[5]; pole1 = pole2;
Obrázek 9: Dvě referenční proměnné odkazující na jeden objekt
Pro kopírování polí můžeme využívat vlastní naprogramovaný kód nebo využít třídu Systém, která obsahuje metodu arraycopy (ta umožňuje efektivně kopírovat data z jednoho pole do jiného). Dva argumenty této metody určují pole, ze kterého a do kterého pole se budou data kopírovat. Tři argumenty int definují počáteční pozici ve zdrojovém poli, počáteční pozici v cílovém poli a počet kopírovaných prvků pole. Příklad kopírování s využitím cyklu: int[] zdrojPole = {2, 3, 1, 5, 10}; int[] cilPole = new int[zdrojPole.length]; for (int i = 0; i < zdrojPole.length; i++) { cilPole[i] = zdrojPole[i]; }
Příklad kopírování s využitím metody arraycopy: int[] zdrojPole = {2, 3, 1, 5, 10}; int[] cilPole = new int[zdrojPole.length]; System.arraycopy(zdrojPole, 0, cilPole, 0, zdrojPole.length);
KST/IZAPR - Základy programování
blok 7, strana 7 (10)
Michael Bažant
7.6 Vícerozměrná pole Vícerozměrná pole slouží k reprezentaci matic nebo tabulek (např. matice vzdáleností měst, matematické maticové operace apod.). V jazyce Java deklarujeme vícerozměrná pole podobně jako pole jednorozměrná. Jen používáme více dvojic operátorů [] – viz následující příklady: datovyTyp[][] refPromenna; Vytvoření samotného objektu, v němž budou uchovány prvky vícerozměrného (v tomto případě dvourozměrného) pole vytváříme (podobně jako u jednorozměrného pole) pomocí operátoru new – viz příklad, kde vytváříme pole o rozměru 10x10 prvků. int matice = new int[10][10]; V jazyce Java jsou vícerozměrná pole poskládaná jednorozměrná pole. To znamená, že referenční proměnná v jednorozměrném poli odkazuje na další objekt typu jednorozměrné pole (viz Obrázek 10).
Obrázek 10: Dvourozměrné pole s prvky primitivního datového typu
Z tohoto důvodu není nutné při vytváření objektu prvotního objektu pro vícerozměrné pole definovat rozměry dalších polí, ale stačí definovat pouze rozměr prvotního jednorozměrného pole referencí na další jednorozměrná pole. Následující příklad je tedy v pořádku: int matice = new int[10][]; Rozměry dalších polí lze stanovit až v dalším kroku při vytváření dalších polí. Tato vlastnost umožňuje vytváření vícerozměrných polí, jejich počet prvků nemusí být vždy stejný (viz Obrázek 10 – první řádek má dva sloupce, druhý řádek tři sloupce apod.). KST/IZAPR - Základy programování
blok 7, strana 8 (10)
Michael Bažant
7.7 Pole referenčních typů Prvky pole samozřejmě nemusí být vždy primitivního datového typu, ale také referenčního datového typu. V takovém případě uvedeme jako datový typ název třídy, jejíž objekty mají být uloženy v poli – viz následující příklad: Student studentNovak = new Student("Novak"); Student[] poleStudentu = {studentNovak, new Student("Novy"), new Student("Novotny")};
Obrázek 11: Jednorozměrné pole referenčních datových typů
S polem se setkáváme v podstatě od samotného začátku programování v jazyce Java, neboť metoda main disponuje parametrem, který představuje pole řetězců. Této vlastnosti metody main lze využít při spuštění programu, kdy lze vkládat argumenty do programu pomocí příkazové řádky – viz následující příklad. public class Student { public static void main(String args[]) { System.out.println("args[0] = " + args[0]); System.out.println("args[1] = " + args[1]); System.out.println("args[2] = " + args[2]); } }
7.8 Chyby v programech Při programování rozlišujeme tři základní druhy chyb: Syntaktické (syntax error) - na tento chyb upozorní kompilátor, např. in i = 10; delka int = 10;
KST/IZAPR - Základy programování
blok 7, strana 9 (10)
Michael Bažant
Chyby za běhu programu (runtime error) - dělení nulou, nerespektování rozsahu polí, např. int i = 10 / 0; Logické (logic error) - špatné výsledky při výpočtech, zpracování dat apod. Tento typ chyb se nejhůře odhaluje a většinou spočívá ve špatném návrhu algoritmu. cenaCelkem = mnozstvi / pocetKusu;
Otázky na procvičení 1. Nakreslete obrázek pro grafickou reprezentaci dvourozměrného pole s prvky primitivního datového typu. 2. Nakreslete obrázek pro grafickou reprezentaci dvourozměrného pole s prvky referenčního datového typu. 3. Musí být uvedeny všechny rozměry vícerozměrného pole již při jeho vytváření? 4. Jaký je index posledního prvku pole? 5. Jaký je index prvního prvku pole?
Odkazy a další studijní prameny 1. Java Tutorial - http://docs.oracle.com/javase/tutorial/
KST/IZAPR - Základy programování
blok 7, strana 10 (10)
Michael Bažant