Co je životní cyklus?
-
Doba mezi vytvořením (new), používáním, nepoužíváním a zánikem objektu (instance).
-
Začíná vytvořením pomocí
new
. -
Faktické používání objektu končí ve chvíli, kdy na něj ztratíme odkaz - např. když odkaz je lokální proměnná metody, kterou opustíme.
-
Fyzická existenci končí buďto koncem programu nebo zrušením objektu pomocí garbage collectoru, "uklízeče smetí".
-
Chování je přibližně stejné jako v Pythonu, ale zcela jiné než v C++ či Rust.
Závislosti mezi objekty
-
správě závislostí mezi objekty, tzn. jeden objekt se své činnosti potřebuje další objekt nebo objekty, se věnuje speciální sekce Dependency Injection.
Vyhnout se zbytečným objektům
-
Avoid unnecessary objects
-
Vytváření objektů je "drahá" operace - stojí výpočetní čas i paměť.
-
Objekt se musí v řadě případů též dealokovat, zlikvidovat, což stojí další čas.
-
V řadě případů není třeba objekt vytvářet, ukážeme si typické situace:
-
řetězce: každé zřetězení
s = s + t
znamená vytvoření nového objektu! -
úplně stejně
s += t
vede k vytvoření nového objektu -
new
namísto zavolání (statické) tovární metody rovněž vždy vytvoří objekt -
řadu složitějších objektů lze vytvořit jen jednou a znovupoužívat
-
pooling (skladiště) objektů
-
Metody místo new
-
Raději
Boolean.valueOf("true")
namístonew Boolean("true")
, neboť to vytvoří pokaždé (obsahově stejný) objektBoolean
-
Obdobně pro další typy - navíc statické metody mohou obecně vrátit i
null
, když se nezdaří. -
U řetezců se mohutně využívá internalizace (neplést s internacionalizací), tzn. uložení do poolu v rámci běžící JVM.
-
Každý řetězec zadaný jako literál (do uvozovek, třeba
"abcde"
) je internalizován a opakované použití odkazuje na tutéž instanci a nezabírá další paměť. -
Internalizaci lze vyvolat i pomocí metody
s.intern()
- u dlouhých řetězců by sdílení mohlo mít smysl! -
Je to proto, že řetězcové literály - nebo obecněji řetězce, které jsou hodnotami konstantních výrazů (§15.28) - jsou "internalizovány" tak, aby sdílely jedinečné instance pomocí metody String.intern (§12.5).
-
blíže viz Java Language Specification, 3.10.5. String literals
Předkompilace u regex
-
Regulární výrazy jsou silnou a častou používanou technikou, jak nalézat nebo ověřovat vzory v řetězcích.
-
Jsou použitelné ve všech běžných jazycích vč. Javy.
-
Lze je buďto:
-
rychle napsat, ale pomalu používat:
"řetězec".matches("regex")
-
zdlouhavěji zapsat a rychle - i opakovaně - vykonávat
-
Pattern pattern = Pattern.compile("regex");
// i opakovaně, bleskově provedeno (násobně rychleji):
String s = ...
if(pattern.matcher(s).matches()) ...
Nepoužívejme finalize()
-
Finalizér, tj. metoda
finalize()
vlastní všem objektům, může teoreticky být překryta a tím umožněn adekvátní "likvidační" postup při zániku objektu - sestávající obvykle z uvolnění systémových zdrojů - síťové sokety, spojení na databázi atd. -
V Javě nicméně není zaručeno, že se finalizér skutečně zavolá - JVM jej nemusí volat, pokud nepotřebuje fyzicky uvolnit paměť obsazenou (již nepoužívaným) objektem.
-
I kdyby finalizér zavolán byl, zůstává problém s určením okamžiku, kdy je volán a v jakém pořadí jsou finalizéry na mrtvých objektech volány.
-
Celkově tedy na
finalize()
nespoléhat a nepoužívat je - zdroje uvolňovat explicitním zavoláním vhodné metody.
Tento tip je javově-specifický, jde o to, jak a kdy pracuje garbage collector při likvidaci nepřístupných ("mrtvých") objektů. |