Vaše jistota na trhu IT Další informace o třídách Rudolf Pecinovský
Vaše jistota na trhu IT Obsah s odkazy ►Práce s textovými řetězciPráce s textovými řetězci ►Regulární výrazyRegulární výrazy ► Další návrhové vzory Další návrhové vzory ► Rozhraní a abstraktní třídy Rozhraní a abstraktní třídy ► Výčtové typy Výčtové typy ► Rozhraní Comparable a Comparator Rozhraní Comparable a Comparator ►Mapy
Vaše jistota na trhu IT Práce s textovými řetězci ►Třída String a její metody ►Formátování řetězců ►Třídy StringBuffer a StringBuilder
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 4 Třída String ►Systémová třída pro práci s textovými řetězci, která je hluboko zapuštěna do virtuálního stroje a může mít proto jistá privilegia: ● Má vlastní literál ● Má vlastní operátory ►Třída String patří mezi neměnné třídy ►Příklady String a, b, c, f; a = "Ahoj"; f = " Franto"; b = a; b += " Franto" c = a + f; if( c == b )... "Ahoj" a b c f " Franto" "Ahoj Franto"
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 5 Neměnné (immutable) typy ►Obsah instance se nastaví v deklaracích a konstruktoru ►Neexistují žádné mutátory (tj. metody set…) ►Atributy jsou většinou definované jako final ►Třída teoreticky může mít proměnné atributy, ale nesmí na nich záviset kód metod equals(Object) ani hashCode() ►Metoda equals(Object) většinou porovnává hodnoty neměnných atributů ►Třídy jsou většinou deklarovány jako konečné ( final ), aby jejich neměnnost nemohli narušit potomci Opakování
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 6 Výhody × nevýhody neměnitelných tříd Jednoduše se s nimi pracuje Jsou spolehlivé při ukládání do množin Jsou spolehlivé jako klíče v mapách Lze s nimi pracovat obdobně jako s hodnotami primitivních typů - Při každé změně hodnoty se musí vytvořit nová instance Opakování
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 7 Metody třídy String 1/3 ► int length() Vrátí délku řetězce, tj. počet znaků v řetzěci ► boolean equals(Object str) boolean equalsIgnoreCase(String str) Porovná řetězec s řetězcem zadaným jako parametr ► int compareTo(String str) int compareToIgnoreCase(String str) Porovná řetězec s řetězcem zadaným jako parametr ► boolean endsWith(String koncovka) boolean startsWith(String počátek) Vrátí informaci o tom, zda řetězec začíná nebo končí řetězcem zadaným jako parametr
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 8 Metody třídy String 2/3 ► char[] toCharArray() Vrátí pole znaků tvořících daný řetězec ► int lastindexOf(char ch) int lastindexOf(char ch, int odPozice) int lastindexOf(String str) int lastindexOf(String str, int odPozice) Vrátí pozici znaku/řetězce zadaného jako parametr; nenachází-li se v řetězci, vrátí -1 ► String substring(int beginIndex) String substring(int beginIndex, int endIndex) Vrátí číst řetězce začínající na dané pozici a končící před zadanou pozicí (není-li zadána, tak do konce) ► String toLowerCase() String toUpperCase() Vrátí řetězec převedený ma malá, resp. velká písmena
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 9 Metody třídy String 3/3 ► static Stringformat(String format, Object... o) Vrátí řetězec vzniklý zformátováním hodnot v poli o podle předpisu v řetězci format ► boolean matches(String regex) Zjistí, zda řetězec vyhovuje zadanému regulárnímu výrazu ► String[] split(String regex) String[] split(String regex, int limit) Rozdělí řetězec podle zadaného regulárního výrazu ► String trim() Vrátí řetězec bez počátečních a koncových bílých znaků ► String replace(???) Sada metod nahrazujících část řetězce zadaným znakem či řetězcem
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 10 Převody mezi čísly a řetězci ► String Double.toString( double d ) String Integer.toString( int i ) Převede zadané číslo na řetězec ► double Double.parseDouble( String s ) int Integer.parseInt ( String s ) Převede zadaný řetězec na číslo ► String String.format(String format, Object... par) Převede zadané parametry na zformátovaný řetězec
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 11 Formátování řetězců1/2 ►Zavedeno ve verzi 5.0 ● static String format(String format, Object... args) ● PrintStream printf(String format, Object... args) ►Specifikace formátu: % [ argument_index ] [ příznaky ] [ šířka ] [. přesnost ] konverze ►Často používané konverze: d celé číslo v dekadickém tvaru x, h celé číslo zapsané hexadecimálně, f desetinné číslo g desetinné číslo, u velkých čísel vědecký formát t formátování datumu a času b boolean s text, výsledek toString(), popř. null
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 12 Formátování řetězců2/2 ►Přesnost = počet míst za desetinnou tečkou ►Šířka = celkový počet zaujímaných pozic (delší text vyteče) ►Příznaky - zarovnání vlevo 0 výsledek se doplní zleva nulami + u kladných čísel bude uvedeno znaménko +, vloží se oddělovač triád dle národního prostředí (u nás se jako oddělovač triád používá mezera) ( Záporná čísla budou uváděna v závorkách Mezera specifikuje, že před kladná čísla bude vždy vložena mezera ►Příklad: String.format("Příjmení:%-30s, Semestr:%2d, Průměr:%4.2f%n", prijmeni, semestr, prumer);
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 13 Třídy StringBuffer a StringBuilder ►Používají se při budování řetězců, abychom se vyhnuli neustálému vytváření a rušení objektů na haldě ►Do verze 1.4 byla v Javě pouze třída StringBuffer, která se snažila zabránit kolizím při současném používání z několika vláken – to zdržovalo ►Java 5.0 přidala třídu StringBuilder, která má všechny metody stejné, pouze se nezdržuje se synchronizací vláken ►Dokud nezačnete vytvářet programy běžící ve více vláknech, dávejte přednost třídě StringBuilder – je rychlejší ►Sčítání řetězců převádí překladač (podle definice jazyka) automaticky na práci s dočasnou instancí StringBuilder
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 14 Metody tříd StringBu???er ►Trojice otazníků symbolizuje, že metody jsou definovány jak pro StringBuffer, tak pro StringBuilder ► StringBu???er append(Ttt t) Přidá stringovou reprezentaci parametru na konec řetězce ● V deklarací je možno dosadit za Ttt libovolný primitivní či objektový typ ► StringBu???er insert(int offset, boolean b) Vloží textovou reprezentaci parametru na zadanou pozici ► StringBu???er delete(int start, int end) Odstraní zadanou část textu ► char charAt(int index) Vrátí znak na zadané pozici
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 15 Ukázky použití1/2 ►Část kódu: bude převedena do tvaru ►Metody append() vracejí odkaz na svoji instanci; tomuto odkazu může být vzápětí poslána zpráva String řádek = "zvíře " + klíč + ", záznam " + mapa.get(klíč); String radek = new StringBuilder().append("zvire ").append(klic).append(", záznam ").append(mapa.get(klic)).toString();
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 16 Ukázky použití2/2 public String poleToString( String titulek, Object[] pole ) { StringBuilder sb = new StringBuilder( titulek ); sb.append( "\n" ); for( int i=0; i < pole.length; i++ ) { sb.append( i ).append( ": " ).append( pole[i] ).append( "\n" ); } return sb.toString(); }
Vaše jistota na trhu IT Regulární výrazy ►Třída String a její metody ►Formátování řetězců ►Třídy StringBuffer a StringBuilder ►Regulární výrazy
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 18 Regulární výrazy ►Nejsou regulérní, ale opravdu regulární ►Zavedené ve verzi 1.4 ►Textová definice požadavků na řetězce ►Definovány v balíčku java.util.regex ● Třída Pattern – vnitřní reprezentace programu definovaného daným regulárním výrazem ● Třída Matcher – interpret dodaného programu nad zadaným výrazem ● Třída PatternSyntaxException ►Příklady využití ● Validaci vstupů ● Kontrole formátu dat ● Dělení řetězce na části podle složitějších kritérií Pattern p = Pattern.compile("a*b"); Matcher m = p.matcher("aaaaab"); boolean b = m.matches();
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 19 Syntaxe regulárních výrazů1/3 ►Jednotlivé znaky: ● S výjimkou znaků speciálního určení vystupuje každý znak sám za sebe ● Platí i escape-sekvence Javy: \\, \uhhhh, \t, \r, \f ● Znak s malým kódem lze hexadecimálně zadat i \xhh ►Množiny znaků [abc] Jeden ze znaků uvnitř závorek (zde a nebo b nebo c) [^abc] Žádný ze znaků uvnitř závorek [a-zA-Z] Rozsah znaků (znaky a až z a znaky A až Z včetně) [a-d[m-p]] Znaky a až d nebo znaky m až p [a-z&&[^qw]] Průnik: znaky a až z s výjimkou znaků q a w [a-z&&[^m-p]] Průnik: znaky a až z s výjimkou znaků m až p
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 20 Syntaxe regulárních výrazů2/3 ►Skupinové znaky. (tečka) Libovolný znak \d Číslice, tj. [0-9] \D NEčíslice, tj. [^0-9] \s Bílý znaky, tj. mezera, tabulátor, konec řádku, konec stránky \S NE bílý znak \w Znak [A-Za-z0-9_] \W Znak [^\w] ►Hranice ^ Začátek řádku $ Konec řádku \b Hranice slova \B Není hranice slova \A Začátek vstupu \Z Konec vstupu \G Konec předchozí nalezené shody
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 21 Syntaxe regulárních výrazů3/3 ►Opakování ? 0 nebo 1 výskyt předchozího znaku * 0 a více výskytů předchozího znaku + 1 a více výskytů předchozího znaku {n} Přesně n opakování předchozího znaku {n,} Minimálně n opakování předchozího znaku {m,n} Minimálně m a maximálně n opakování předchozího znaku ►Další operátory XY Znaky X a Y musí být vedle sebe, X|Y Buď znak X nebo znak Y, (X) Označení skupiny, \n Obsah n-té skupiny,
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 22 Příklady užití regulárních výrazů ►Zadání: Definujte regulární výraz umožňující ověřit, že řetězec odpovídá vodáckému pokřiku public static void ahoj() { String[] as = {"ahj", "ahoj", "ahooj", "ahoooj"}; for( String s : as ) { String t = "aho+j"; System.out.println( s + " == " + s.matches( t ) ); }
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 23 Příklady užití regulárních výrazů ►V regulárním výrazu zapsaném ve zdrojovém textu musí být všechna zpětná lomítka zdvojená ►Zadání: Napište regulární výraz, pomocí kterého je možno najít odstranit všechny zdvojené mezery v zadaném textu public static void mezery() { String[] as = { "a b c d", "a b c de" }; String rv = "\\s{2,}"; for( String s : as ) { System.out.println( s + " == " + s.replaceAll( rv, "_" ) ); }
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 24 Příklady užití regulárních výrazů ►Zadání: Napište regulární výraz, pomocí kterého je možno zjistit, zda lze v Javě daný řetězec považovat za identifikátor public static void identifikátor() { String[] as = { "12a", "_123", "$a7", "_$_" }; String rv = "[\\$\\w&&\\D][\\w\\$]*"; for( String s : as ) { System.out.println( s + " == " + s.matches( rv ) ); }
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 25 Příklady užití regulárních výrazů ►Zadání: Rozdělte text na slova public static void slova() { String[] as = { "a b c d", "a b c de" }; String rv = "\\s+"; for( String s : as ) { String[] ss = s.split( rv ); System.out.print( s + " == " ); for( String w : ss ) System.out.print( w + "*" ); System.out.println(); }
Vaše jistota na trhu IT Výčtové typy ►Jednoduchý výčet hodnot ►Jak to vypadá uvnitř ►„Chytřejší“ výčtové typy ►Příklad: třída Směr8 253–256 67–72
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 27 Syntaxe výčtových typů ►V definicích výčtových typů je klíčové slovo class nahrazeno slovem enum ►Za hlavičkou třídy následuje seznam hodnot daného typu ►Za čistým výčtem dokonce nemusí následovat středník ►Uvedený typ překladač přeloží stejně, jak by byl definován jako potomek třídy java.lang.Enum public enum Období { JARO, LÉTO, PODZIM, ZIMA; }
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 28 Přeložený tvar čistého výčtu package výčty; public final class Období extends Enum { public static final Období JARO; public static final Období LÉTO; public static final Období PODZIM; public static final Období ZIMA; private static final Období $VALUES[]; static { JARO = new Období("JARO", 0); LÉTO = new Období("LÉTO", 1); PODZIM = new Období("PODZIM", 2); ZIMA = new Období("ZIMA", 3); $VALUES = new Období[] { JARO, LÉTO, PODZIM, ZIMA }; } public static final Období[] values() { return (Období[])((Období []) ($VALUES)).clone(); } public static Období valueOf(String name) { return (Období)Enum.valueOf(výčty.Období, name); } private Období(String s, int i) { super(s, i); } Pole hodnot daného typu Deklarace hodnot (veřejných konstant) daného typu Statický inicializační blok inicializující konstanty a pole s odkazy na ně Metoda vracející pole hodnot daného typu Metoda vracející hodnotu po zadání jejího názvu Soukromý konstruktor zabraňující vytváření dalších instancí
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 29 Metody zděděné od třídy Enum ► String name() Vrátí název dané instance ► int ordinal() Vrátí pořadí deklarace dané instance (začíná se nulou) ► boolean equals(Object other) Vrací true je-li instance totožná s parametrem ► int compareTo(E o) Vrátí -1, 0 či +1 podle toho, je-li deklarace daná instance menší, rovna či větší než parametr (porovnává se ordinal ) ► E[] values() ► E valueOf(String name) Jsou zde uvedeny pro úplnost, nedědí se, dodá je překladač (viz předchozí snímek)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 30 „Chytřejší“ výčtové typy ►Často je výhodné, aby hodnoty výčtového typu vykazovaly jistou „dodatečnou inteligenci“ ►Výčtové typy nemusí být pouze čistým výčtem hodnot, jsou to standardní typy ● Mohou mít vlastní atributy a vlastnosti ● Mohou mít vlastní metody ● Mohou využívat konstruktoru s parmaetry ►Příklad: Směr8
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 31 Vytváření instancí třídy Směr8 public enum Směr8 { //== HODNOTY VÝČTOVÉHO TYPU ================================================== VÝCHOD ( 1, 0, "V", "VYCHOD" ), SEVEROVÝCHOD( 1, -1, "SV", "SEVEROVYCHOD" ), SEVER ( 0, -1, "S", "SEVER" ), SEVEROZÁPAD ( -1, -1, "SZ", "SEVEROZAPAD" ), ZÁPAD ( -1, 0, "Z", "ZAPAD" ), JIHOZÁPAD ( -1, 1, "JZ", "JIHOZAPAD" ), JIH ( 0, 1, "J", "JIH" ), JIHOVÝCHOD ( 1, 1, "JV", "JIHOVYCHOD" ), ; //== KONSTANTNÍ ATRIBUTY TŘÍDY =============================================== public static final int SMĚRŮ = 8; private static final int MASKA = 7; private static final Map názvy = new HashMap ( SMĚRŮ*3 ); private static final int[][] posun = new int[SMĚRŮ][2]; private static final Směr8[] SMĚRY = values(); static { for( Směr8 s : SMĚRY ) { posun[s.ordinal()][0] = s.přepravka.dx; posun[s.ordinal()][1] = s.přepravka.dy; názvy.put( s.přepravka.zkratka, s ); názvy.put( s.přepravka.název, s ); názvy.put( s.přepravka.názevBHC,s ); s.přepravka = null; } //== DOČASNÉ ATRIBUTY INSTANCÍ =============================================== private static class Přepravka { int dx, dy; String zkratka, název, názevBHC; } Přepravka přepravka; //== KONSTRUKTORY A TOVÁRNÍ METODY =========================================== private Směr8( int dx, int dy, String zkratka, String názevBHC ) { přepravka = new Přepravka(); přepravka.dx = dx; přepravka.dy = dy; přepravka.zkratka = zkratka; přepravka.název = name(); přepravka.názevBHC = názevBHC; } Deklarace hodnot (veřejných konstant) daného typu Instance si svá data pamatují v polích, která jsou atributy třídy Statický inicializační blok inicializující pole a mapu hodnotami z přepravky Mapa pro získání instance zadaného názvu či zkratky Přepravka pro dočasné uchování hodnot zadaných konstruktoru, než je bude možno uložit do mapy a příslušných polí Konstruktor ukládá všechny parametry do přepravky, aby je bylo možno vyzvednout ve statickém inicializačním bloku
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 32 Výběr rozšiřujících metod třídy Směr8 public Směr8 čelemVzad() { return SMĚRY[MASKA & (4+ordinal())]; } public int dx() { return posun[ordinal()][0]; } public int dalšíX( int x, int vzdálenost ) { return x + dx()*vzdálenost; } public Pozice dalšíPozice( Pozice pozice, int vzdálenost ) { return new Pozice( dalšíX( pozice.x, vzdálenost ), dalšíY( pozice.y, vzdálenost ) ); }
Vaše jistota na trhu IT Užitečné třídy a metody
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 34 Náhoda ►Náhodné číslo lze získat voláním metody java.lang.Math.random ● Vrátí číslo typu double v rozsahu [0;1)
Vaše jistota na trhu IT Další návrhové vzory ►Knihovní třída ►Jednoduchá tovární metoda ►Jedináček ►Výčtový typ ►Originál 249–256
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 36 Návrhový vzor Knihovní třída ►Knihovní třída slouží pouze jako obal na sadu třídních metod ►Protože obsahuje pouze třídní metody, nepotřebuje instance ►Aby nikdo nemohl vytvářet její instance ani omylem, mívá definován soukromý prázdný bezparametrický konstruktor ►Příklady, s nimiž jsme se již setkali: ● IO sada okenních vstupních a výstupních funkcí ● java.lang.Math sada matematických funkcí + konstanty a e ● java.lang.System měření času, standardní IO, komunikace se systémem ● java.util.Arrays třídění, vyhledávání a další operace s poli ● java.util.Collections třídění, vyhledávání a další operace s kolekcemi)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 37 Návrhový vzor Jednoduchá tovární metoda ►Veřejná, statická metoda, která se tváří, že umí vytvořit instanci ►Používá se potřebujeme-li skrýt před zbytkem světa konstruktor, abychom udrželi vytváření instancí ve vlastní režii ►Metoda volá konstruktor, který ale bývá soukromý, takže je z oblasti mimo třídu nedosažitelný ►Typické názvy: ● getInstance ● getNázevTřídy (např. getPlátno, getBarva )
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 38 Návrhový vzor Jedináček (Singleton) ►Používá se, potřebujeme-li, aby třída měla jedinou instanci ►Známý příklad: Plátno ►Aby zůstalo vytváření instancí třídy v její režii, definuje třída opět soukromý konstruktor ►Její jediná instance (jedináček) je deklarována jako její statický konstantní (většinou soukromý) atribut, který je inicializován již v deklaraci ►K získání odkazu na instanci se místo konstruktoru používá jednoduchá tovární metoda
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 39 Příklad: třída Jedináček public final class Jedináček { private static final Jedináček jedináček = new Jedináček(); private String krédo; private Jedináček() { krédo = "V mládí jsem byl namyšlený, " + "ale nyní jsem již dokonalý"; } public static Jedináček getInstance() { return jedináček; } public String toString() { return krédo; }
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 40 Návrhový vzor Výčtový typ ►Používá se, pokud potřebujeme pracovat s předem známým počtem předem známých hodnot ►Aby nebylo možno počet hodnot rozšiřovat, definuje třída konstruktor jako soukromý ►Hodnoty jsou definovány jako veřejné třídní konstanty inicializované (zavoláním konstruktoru) již v deklaraci ►Java 5.0 začlenila tento návrhový vzor do své syntaxe; výčtové typy jsou zvláštním druhem třídy (za chvíli je probereme podrobněji) ►Příklad: Směr8
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 41 Návrhový vzor Originál ►Používá u hodnotových typů, u nichž očekáváte sice předem neznámý, nicméně relativně malý počet vytvořených instancí ►Třída si hlídá, aby nevznikly dvě instance se stejnou hodnotou (zobecněný jedináček) ►Definuje konstruktor jako soukromý, odkaz na instanci lze získat prostřednictvím jednoduché tovární metody ►Tovární metoda nechá vyrobit novou instanci pouze tehdy, pokud ještě žádná instance s danou hodnotou neexistuje ►Výhody: ● Nezahlcuje se paměť neustále vytvářenými a rušenými instancemi ● Místo equals(Object) lze použít operátor == ►Příklad: Barva
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 42 Návrhový vzor Příkaz ►Podobný jako služebník, jenom nahlíží na problém z druhé strany ►Mám definovanou metodu, jejímž parametrem má být akce ►Definuji rozhraní specifikující požadovanou akci – příkaz, a instanci tohoto rozhraní deklaruji jako parametr metody ►Kdo bude chtít využívat metodu, musí definovat akci a obalit ji objektem implementujícím dané rozhraní ►Příklad: komparátor a třídící a vyhledávací metody
Vaše jistota na trhu IT Děkuji za pozornost Rudolf Pecinovský mail: ICQ: