Tvorba objektů Objekty lze vytvářet, operovat nad nimi, ukládat je na vnější paměti, přenášet je či využívat telekomunikačně pouze v čase běhu ( run-time ). Objekt ( = instance třídy ) se vytváří v operační paměti na haldě ( = heap ). Objekt nemusí být kontinuální v paměti - bývá v paměti rozmítán. Obsahuje instanční, tj. nestatické, atributy primitivních i referenčních typů. Objekt vytváří konstruktor a event. dotvářejí nestatické inicializátory. Každý objekt referuje jedinečný class-object popisující jeho třídu, jenž obsahuje statické čili třídní atributy a reference ke kódům metod, konstruktorů a inicializátorů. Tam kódy existují jen v jediném exempláři, jsou tzv. reentrantní, tj. neobsahují proměnná data a tudíž dle nich může postupovat více vláken současně. V objektech žádné kódy nejsou. JVM vede vlastní evidenci vytvořených objektů a referencí k nim. Nereferované objekty ruší při nedostatku paměti garbage collector. Ten lze i programově zavolat metodou System.gc( ) či Runtime.gc( ) ; PJV02
Konstruktory Konstruktor vytváří na haldě objekt a dle parametrů nastaví jeho atributy. Připomíná konkrétní nestatickou nefinální metodu ( funkci ), která: jméno musí mít stejné jako třída, nemá vyjádřený návratový typ, má modifikátory viditelnosti ( private – zabrání tvorbě objektů zevně ), není členem třídy a nedědí se a tudíž ho nelze překrýt, konstruktory lze přetěžovat podobně jako metody, v těle může mít příkazy return samozřejmě bez návratové hodnoty. Každá třída - i abstraktní - má alespoň jeden konstruktor ( byť skrytý ). Není-li ve třídě žádný explicitní konstruktor definován, vytvoří se skrytý: public JménoTřídy ( ) { super( ); } tj. implicitní konstruktor bez parametrů, který volá bezparametrický konstruktor přímého předka. Je-li však nějaký konstruktor explicitně definován, pak se onen implicitní nevytvoří a eventuálně požadovaný konstruktor bez parametrů je nutno definovat explicitně – případně i s neprázdným tělem. PJV02
Vzájemné volání konstruktorů Pro začátek těl konstruktorů platí tato pravidla pro tři případy: 1. public JménoTřídy ( ... ) { super(…); … } Zprvu se vždy volá příslušný existující konstruktor přímého předka. 2. public JménoTřídy ( ... ) { this(…); … } Zprvu se volá existující přetížený konstruktor téže třídy. Tuto fintu lze použít i několikrát, avšak nesmí dojít k cyklu. Začíná-li však tělo jinak, skrytě se přidá volání super( ) takto: 3. public JménoTřídy ( ... ) { … } public JménoTřídy ( ... ) { super( ); … } Vyhodí-li konstruktor či nestatický inicializátor výjimku, objekt nevznikne. Lze-li z třídy dědit, její konstruktory by neměly volat překrývatelnou metodu této třídy, aby se jeho chování nenarušilo překrytím. jsou ekvivalentní PJV02
Vytvoření objektu instanciací třídy, tj. aktivací konstruktoru operátorem new : new Type( … ) resp. new Type( … ) { ... } - kde Type je jméno třídy resp. interfejsu pro pole: new Type[ num ] resp. new Type[ ] { ..., ..., ... } - kde Type je jméno třídy, interfejsu nebo primitivní typ. Každé pole ( i primitivů ) lze referovat též typem java.lang.Object. klonováním pomocí generální metody clone( ) natažením ze serializovaného proudu nestatickou metodou java.lang.Class.newInstance( ) - např. takto: Class c = Class.forName( "ÚplnéJménoTřídy" ); Object x = c.newInstance( ); ÚplnéJménoTřídy z = ( ÚplnéJménoTřídy ) x; PJV02
Inicializace nestatických atributů Nestatické atributy se inicializují při konstrukci každého objektu. Nejdříve dle společného pořadí deklarací a nestatických inicializátorů a pak v pořadí dokončovaných těl konstruktorů. Nestatické čili instanční inicializátory připomínají metody mající přístup k nestatickému i statickému kontextu, nic nevracejí, nemají signaturu, nevyznačují výjimky, nelze je volat, nejsou členy třídy a nedědí se. Lze jich deklarovat i více, vykonávají se po pořadí . Syntakticky jsou to pouhé bloky: { ... } Příklad: final static byte MARK = 0xff; byte[ ] a = new byte [ 256 ] ; // translation table { for ( int i = 0; i < a.length; i++ ) a[ i ] = ( byte ) i; } { a[ 100 ] = MARK; } Nestatické inicializátory se užívají např. v anonymních třídách. PJV02
Postup konstrukce objektu je tím obtížnější čím je jeho třída dále od kořene a čím má větší bohatství. Po zavolání konstruktoru se: Alokuje paměť a inicializují se nestatické atributy na defaultní hodnoty. Postupně volají konstruktory všech nadtříd ( směrem nahoru ) až k java.lang.Object a to příkazem super(…) volající existující konstruktor příslušné signatury. Postupně se ( směrem dolů ) dle každé třídy re-inicializují nestatické atributy ( případně i nestatickými inicializátory ) a teprve pak se dokončí těla jejich volaných konstruktorů. Proces konstrukce se může i stromově větvit - např.: int i = 100, j = i+10, w = 300, h = w/2 ; Rectangle r = new Rectangle( new Point( i, j ), new Dimension( w, h ) ); PJV02
Postup konstrukce objektu Těla konstruktorů a nestatických inicializátorů mohou obsahovat i volání statických i nestatických metod. Upozornění: Je-li nestatická metoda překryta v potomkovi a je volána v konstruktoru či nestatickém inicializátoru předka, pak se vezme metoda potomka. Tomuto jevu lze zabránit: metoda předka se skryje přísnějším přístupovým modifikátorem – ( např. private ), čímž se tato metoda nepřepíše. či použitím statické metody. PJV02
Příklad (1/2) class Book extends Object implements Comparable { private static int total; private final int id; private final String title; public Book( String title ) { this.title = title; id = ++total; } public static int getTotal( ) { return total; } public int getld( ) { return id; } public String getTitle( ) { return title; } public int compareTo( Object o ) { if ( ! (o instanceof Book) ) System.out.println( "ClassCastException" ); Book that = ( Book ) o; // can be thrown here return this.title.compareTo( that.title ); } public String toString( ) { return " Book: " +id+ " "+title; } } // Inicializace vytvoří objekty a reference ( viz dále ): Book b0 = null, b1 = new Book("A"), b2 = new Book("B"), b3 = new Book("JAVA_7") ; PJV02
garbage collected heap Příklad (2/2) non-static context static context static memory Object.class garbage collected heap class loader references anywhere Object( ) non-static general methods: clone( ), equals( ), hashCode( ), finalize( ), getClass( ), notify( ), notifyAll( ), toString( ), wait(…) b3 b2 b1 b0 = null Comparable.class Book objects int compareTo(…); final class final class Book.class final class int id 3 Book( String title ) static getTotal( ) toString( ), getId( ), getTitle( ), compareTo( …) String title static int total 3 String object String.class final class String( … ) static format( ), valueOf( ) toString( ), compareTo( …), length( ), charAt( ), equals( ) char[ ] final int length JAVA_7 6 PJV02
Nepostradatelný balíček java.lang Tudíž netřeba psát import java.lang.*; Obsahuje základní interfejsy, třídy, Enum, Exceptions, Errors a anotace. A dále podbalíčky: java.lang.annotation – pro podporu anotací (od v. 1.5) java.lang.instrument – pro redefinici tříd (od v. 1.5) java.lang.invoke – pro podporu dynamiky (od v. 1.7) java.lang.management – pro sledování a řízení JVM (od v. 1.5) java.lang.ref – pro práci s referencemi a garbage collectorem. java.lang.reflect – pro reflexi, tj. detailní práci s třídami a objekty. PJV02
<E ex. Enum <E> > @FunctionalInterface java.lang Object Cloneable Enum java.lang.reflect AnnotatedElement System Iterable <E ex. Enum <E> > <T> java.io Class Runtime Comparable Serializable <T> <T> Process String Appendable 1.5 Process Builder CharSequence StringBuffer StringBuilder 1.8 syn nosyn 1.0 1.5 Package Class Loader java.security java.net Compiler SecureClass Loader URLClass Loader @FunctionalInterface PJV02 ALG
@FunctionalInterface java.lang Security Manager Runnable Thread.Uncaught ExceptionHandler Readable read() run() uncaughtException() java .rmi AutoCloseable Thread ThreadGroup RMISecurity Manager 1.7 close() java.io Closeable close() java.io ThreadLocal java.nio java.rmi java.sql <T> javax.imageio … Inheritable ThreadLocal java.security java.io Permission <T> Serializable Thread. State java.security StackTrace Element Basic Permission ClassValue Runtime Permission @FunctionalInterface 1.7 <T> PJV02 ALG
java.lang * * * * * … Byte Short Integer Float Long Double Boolean * má skrytý pool hodnot -128 … 127 # viz potomci v static Byte java.util.concurrent .atomic Character. Subset Serializable * Short wrapper classes static Character. UnicodeBlock java.io * Number Integer # Float java.awt * Long # Double InputSubset wrapper classes Boolean # Math Comparable * * má skrytý pool hodnot \u0000 …\u007F Character <T> compareTo() @Deprecated StrictMath java.math BigInteger BigDecimal @Override java.util.concurrent.atomic Void AtomicInteger AtomicLong … @Suppressed Warning PJV02 ALG
java.lang Throwable Exception Serializable checked unchecked Runtime java.io Serializable checked unchecked Throwable Exception Runtime Exception EnumConstNot PresentException CloneNotSupported Exception NullPointer Exception ClassNotFound Exception TypeNot PresentException IllegalAccess Exception ClassCast Exception IndexOutOf BoundsException ArrayIndexOutOf BoundsException Instantiation Exception Arithmetic Exception StringIndexOutOf BoundsException Interrupted Exception ArrayStore Exception IllegalArgument Exception NumberFormat Exception NoSuchField Exception NegativeArray SizeException Unsupported OpException IllegalThread StateException NoSuchMethod Exception IllegalMonitor StateException Security Exception Illegal StateException PJV02 ALG
java.lang Throwable Error Serializable unchecked Linkage Error java.io Assertion Error ClassCircularity Error Serializable ThreadDeath Error ClassFormat Error UnsupportedClass VersionError java.lang Virtual MachineError IncompatibleClass ChangeError Abstract MethodError Unknown Error ExceptionIn InitializerError IllegalAccess Error StackOverflow Error NoClassDef FoundError Instantiation Error OutOfMemory Error Unsatisfied LinkError NoSuchField Error Internal Error VerifyError NoSuchMethod Error PJV02 ALG
Třída java.lang.Object je kořenem jediného stromu všech tříd. Nemá žádné dostupné atributy, má jen implicitní konstruktor a 11 přetížených, dostupných, instančních metod, které zdědí všichni potomci. public boolean equals( Object obj ) - definuje relaci ekvivalence objektů ( tj. reflexivní, symetrická, transitivní a konstantní ), vrací true při identitě, tzn. právě tehdy, když this == obj. Při překrytí, je nutné dodržet kontrakt tj. překrýt i metodu hashCode. public native int hashCode( ) – má dodržet kontrakt a vracet číslo jež: - je konstantní v jednom běhu – nezměnily-li se údaje užité v equals( ). ( Např.: deserializovaný transient atribut zhatí kontrakt. Z kolekce je takový objekt nutno vyjmout a znova vložit. ) - ekvivalentní objekty - dle equals( ) - musejí vracet totéž číslo. - neekvivalentní objekty - dle equals( ) - nemusejí vracet různá čísla. Důsledek pro objekty téže třídy: hash1 != hash2 pak obj1 != obj2. Dosti rovnoměrně rozrůzněná čísla zlepšují funkci hešových tabulek. PJV02
Třída java.lang.Object public final native Class<?> getClass( ) - vrací objekt typu Class, který popisuje jeho třídu - čili typ a detaily. public String toString( ) - vydává popisný řetěz. Radno ji v potomcích překrýt tak, aby vrátila typ a stav objektu. Volá se automaticky při konkatenaci s řetězem a v metodách např. print(...) či println(...). public native final void wait(...) throws InterruptedException – tyto tři metody pozastaví vlákno a zařadí ho do čekárny na určitý objekt. Případně lze zadat maximální dobu čekání. public native final void notifyAll( ) - uvolňuje všechna čekající vlákna. public native final void notify( ) - uvolňuje některé čekající vlákno. protected native Object clone( ) throws CloneNotSupportedException - pro mělké klonování objektů. PJV02
Třída java.lang.Object protected void finalize( ) throws Throwable – tuto metodu volá garbage collector jen jednou při rušení objektu. Překrytá může provést: - nějaké úkony před zrušením objektu – např. získat jeho data. Metoda musí zavolat super.finalize( ). - zachránit objekt tak, aby byl dosažitelný z nějakého nemrtvého vlákna. Vyhození Throwable se ignoruje, ale rušení objektu se zastaví. JVM nezaručuje, které vlákno tuto metodu provede. Garbage collector lze vyvolat metodou System.gc( ) či Runtime.gc( ), JVM ho aktivuje při nedostatku požadované souvislé paměti – neaktivuje však při ukončování aplikace. PJV02
Finální třída java.lang.String Řetězy nejsou primitivy ale neměnné ( immutable ) objekty typu String. Řetězové literály se ukládají do String Constant Poolu. Konstruktory mají parametry: String, byte[ ], char[ ], Charset … Nejdůležitější metody: int length( ) / boolean isEmpty( ) – zjištění délky char charA( int index ) – výběr jednoho znaku řetězu int compareTo( String o ) – porovnání dvou řetězů boolean equals ( Object o ) / equalsIgnoreCase ( String s ) byte[ ] getBytes ( ) – převod na pole bytů int indexOf( String s ) / lastIndexOf( String s ) – hledání substringu boolean matches( String regex ) – hledání vzorku dle regulárního výrazu int String[ ] split( String regex ) – separace dle regulárního výrazu String replace( char old, char new ) – zamění znaky - v novém řetězu String substring( int begin ) / substring( int begin, int end ) String trim( ) – vyloučí oba bílé konce nového řetězu String toUpperCase( ) / toLowerCase( ) - vytváří nový změněný řetěz String concat( String s ) – přiřetězení vytváří nový řetěz PJV02
Finální třídy java.lang. StringBuffer a StringBuilder Umožňují shodné operace s řetězy. StringBuffer je synchronizovaný, StringBuilder není – avšak je rychlejší a doporučuje se. Oba nejsou Comparable a nemají překrytou metodu equals( ) . char charA( int index ) – vrátí znak na indexu StringBuilder append( … ) – připojí na konec StringBuilder insert( int offset, … ) – vloží do StringBuilder delete( int begin, int end ) – vyjme int length( ) – int indexOf( String s ) – vrátí index offsetu anebo -1 int lastIndexOf( String s ) – vrátí index offsetu anebo -1, hledá od konce String replace( char old, char new ) String reverse( ) – vrátí obrácený řetěz String substring( int begin ) – vrátí výstřižek až do konce String substring( int begin, int end ) – vrátí výstřižek String trimToSize( ) – vrátí řetěz obraný o bílý prefix a sufix String toString( ) – vrátí svůj obsah PJV02
Interfejs java.lang.Comparable < T > definuje tzv. naturální porovnání metodu public int compareTo ( T that ); // abstraktní metoda vracející <0, 0, >0 pro this < that, this == that, this > that Lexikografické porovnání řetězů: int n = s1.compareTo( s2 ); Numerické porovnání: class Item implements Comparable { // příklad String title; // název výrobku float price = 0f; // cena výrobku public int compareTo( Object o ) { Item that = ( Item ) o; if ( this.price == that.price ) return 0; return this.price > that.price ? 1 : -1 ; // pro řazení vzestupně } PJV02
Interfejs java.lang.Iterable < T > Podporuje prohlížení obecných kolekcí objektů. Definuje: public Iterator <T> iterator ( ); // abstraktní metoda public default forEach( Consumer<? super T> action ) public default Spliterator<T> spliterator( ) 1.8 1.8 PJV02
Finální třída java.lang.System má static atributy: InputStream in, PrintStream out a err a metody: void arraycopy( Object src, int sPos, Object d, int dPos, int length ) - kopie long currentTimeMillis( ) – UTC čas v milisekundách od 01 JAN 1970 void exit( int code ) – zborcení aplikace a vrací určené číslo void gc( ) – spustí garbage collector - skrze Runtime.gc( ) Map<String, String> getenv( ) - informace o prostředí String getenv( String env ) - informace o prostředí Properties getProperties( ) - vlastnosti prostředí void setProperties( Properties props ) - nastavení vlastnosti prostředí String clearProperty( String key ) void load( String filename ) void loadLibrary( String filename ) String mapLibraryName( String libname ) void setIn( InputStream is ), void setErr( PrintStream ps ), setOut( PrintStream ps ) – přesměrování SecurityManager getSecurityManager( ) Console console( ) – vrací unikátní objekt asociovaný s JVM PJV02
Třídy java.lang. ProcessBuilder, Process a Runtime umožňují určitý styk se operačním systémem a spouštět v něm programy. ProcessBuilder pb = new ProcessBuilder( "prog" , "arg1", "arg2", … ); pb.directory( new File( "C:/ … ") ); // set working folder Process p = pb.start( ); InputStream is = p.getInputStream( ); // process piped output … // read and so … System.out.println( "exitValue="+p.waitFor() ); // waiting for end Runtime r = Runtime.getRuntime( ); Process p = r.exec( prog, env, dir ); p.waitFor( ); // waiting for end System.out.println( " p= " + p.exitValue( ) ); // completion code long m = r.freeMemory( ); r.loadLibrary( name ); r.gc( ); // call garbage collector PJV02