{"id":40,"date":"2013-01-18T17:11:44","date_gmt":"2013-01-18T16:11:44","guid":{"rendered":""},"modified":"2018-09-17T21:56:12","modified_gmt":"2018-09-17T19:56:12","slug":"ako-si-java-robi-poznamky","status":"publish","type":"post","link":"https:\/\/spireng.sk\/en\/ako-si-java-robi-poznamky\/","title":{"rendered":"Ako si Java rob\u00ed pozn\u00e1mky"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"imgp_img\" style=\"float: left; margin: 2px 5px;\" src=\"\/sites\/default\/files\/imagepicker\/1\/dfsfd45dfs.jpg\" alt=\"Obr\u00e1zok\" width=\"200\" height=\"157\" \/>Pokia\u013e sa z\u00fa\u010dast\u0148ujete v\u00e4\u010d\u0161ieho projektu tak je mo\u017en\u00e9, \u017ee sk\u00f4r alebo nesk\u00f4r naraz\u00edte na probl\u00e9m, ktor\u00fd je ve\u013emi be\u017en\u00fd. Chcete serializova\u0165\/deserializova\u0165 objekty. Teda prev\u00e1dza\u0165 ich \u00fadaje v pam\u00e4ti na pr\u00fad bajtov (niekedy znakov) a to tak, aby ste ich v inom \u010dase alebo na inom mieste vedeli pre\u010d\u00edta\u0165 nasp\u00e4\u0165. Ako mnoh\u00e9 vyspel\u00e9 jazyky, aj Java m\u00e1 pre tento probl\u00e9m hotov\u00e9 rie\u0161enie. Po\u010fme sa na neho pozrie\u0165.<!--more--><!--break--><\/p>\n<p>Na to, aby sa v\u00e1m podarila \u00faspe\u0161n\u00e1 serializ\u00e1cia alebo deserializ\u00e1cia, potrebujete 2 veci. Potrebujete riadiaci objekt, pomocou ktor\u00e9ho spust\u00edte a budete riadi\u0165 proces z\u00e1pisu alebo \u010d\u00edtania. A potrebujete d\u00e1tov\u00fd objekt, ktor\u00fd bude zap\u00edsan\u00fd a ktor\u00fd mus\u00ed by\u0165 upraven\u00fd, aby ho ten prv\u00fd vedel pou\u017ei\u0165. Ak m\u00e1te tieto dve zlo\u017eky, je to v\u0161etko, \u010do potrebujete a serializ\u00e1ciu m\u00e1te vyrie\u0161en\u00fa.<\/p>\n<p>V pr\u00edpade, \u017ee nem\u00e1te na serializ\u00e1ciu nejak\u00e9 \u0161peci\u00e1lne po\u017eiadavky, tak v\u00e1m Java dod\u00e1 prv\u00fd spom\u00ednan\u00fd objekt a ve\u013emi pom\u00f4\u017ee s druh\u00fdm. Je to mechanizmus, ktor\u00fd budem vola\u0165 <em>nat\u00edvna serializ\u00e1cia<\/em>, preto\u017ee je to \u0161tandardn\u00e1 serializ\u00e1cia, ktor\u00fa viete pou\u017ei\u0165 pre be\u017en\u00e9 pr\u00edpady. V takom pr\u00edpade v\u00e1m Java dod\u00e1va dve riadiace triedy a to <em>ObjectOutputStream<\/em> a <em>ObjectInputStream<\/em>. \u010co sa t\u00fdka pr\u00fadov (Stream) v Jave, tak sa tam s ve\u013ekou ob\u013eubou pou\u017e\u00edva n\u00e1vrhov\u00fd vzor <em>Wrapper<\/em>. Aj tieto dve spom\u00ednan\u00e9 triedy s\u00fa len ob\u00e1lky, do ktor\u00fdch mus\u00edte vlo\u017ei\u0165 nejak\u00fd in\u00fd vstupn\u00fd alebo v\u00fdstupn\u00fd pr\u00fad. M\u00f4\u017ee to by\u0165 napr\u00edklad pr\u00fad vzniknut\u00fd po otvoren\u00ed s\u00faboru.<\/p>\n<p style=\"padding-left: 30px;\"><code>ObjectOutputStream objectDeserializer = new ObjectOutputStream( new BufferedOutputStream(Files.newOutputStream(file)))) ;<\/code><\/p>\n<p>D\u00f4le\u017eit\u00e9 je, \u017ee tieto \u0161peci\u00e1lne pr\u00fady maj\u00fa dve p\u00e1rov\u00e9 met\u00f3dy <em>readObject(Object o)<\/em> a <em>writeObject(Object o)<\/em>. Tie potom viete pou\u017ei\u0165 na postupn\u00fd z\u00e1pis\/\u010d\u00edtanie va\u0161ich objektov. A to by mohlo by\u0165 z poh\u013eadu riadenia v\u0161etko. Ako ale maj\u00fa vyzera\u0165 objekty, ktor\u00e9 chcete zapisova\u0165\/\u010d\u00edta\u0165?<\/p>\n<p>Objekt, ktor\u00fd m\u00e1 fungova\u0165 s nat\u00edvnou serializ\u00e1ciou mus\u00ed sp\u013a\u0148a\u0165 3 podmienky:<\/p>\n<p style=\"padding-left: 30px;\">1. objekt mus\u00ed ma\u0165 <em>public<\/em><span style=\"font-style: normal;\"> modifik\u00e1tor pr\u00edstupu,<\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"font-style: normal;\"> 2. mus\u00ed implementova\u0165 rozhranie <\/span><em>Serializable,<\/em><\/p>\n<p style=\"padding-left: 30px;\">3. predkovia triedy (od ktor\u00fdch je odvoden\u00e1) musia sp\u013a\u0148a\u0165 predch\u00e1dzaj\u00face dve podmienky.<\/p>\n<p><span style=\"font-style: normal;\">Urobi\u0165 public triedu asi nie je \u017eiaden probl\u00e9m. \u010co znamen\u00e1 implementova\u0165 rozhranie <\/span><em>Serializable<\/em><span style=\"font-style: normal;\">? No, ve\u013ea nie. To rozhranie je toti\u017e v podstate pr\u00e1zdne (k tomu, pre\u010do v \u201epodstate\u201c sa dostanem o chv\u00ed\u013eu). Ide hlavne o to, \u017ee t\u00fdmto rozhran\u00edm ozna\u010d\u00edte triedu, \u017ee je serializovate\u013en\u00e1. Okrem toho je dobr\u00e9 do tried doplni\u0165 tak\u00fato premenn\u00fa:<\/span><\/p>\n<p style=\"padding-left: 30px;\"><code> private static final long serialVersionUID = 2045L;<\/code><\/p>\n<p><span style=\"font-style: normal;\">Presn\u00e1 hodnota a modifik\u00e1tor pr\u00edstupu nie je a\u017e tak\u00fd podstatn\u00fd. To, \u010do mus\u00ed by\u0165 zachovan\u00e9, je n\u00e1zov a typ (a modifik\u00e1tor <\/span><em>static<\/em><span style=\"font-style: normal;\">). Na \u010do to sl\u00fa\u017ei? Pomocou tejto premennej Java vie, \u010di pri deserializ\u00e1cii \u010d\u00edta rovnak\u00fa verziu objektu ako zapisovala. Ak sa \u010d\u00edslo zhoduje, je to ten ist\u00fd objekt, ak nie, tak m\u00f4\u017eete dosta\u0165 v\u00fdnimku <\/span><em>InvalidClassException .<\/em><span style=\"font-style: normal;\"> Z toho tie\u017e vypl\u00fdva, \u017ee pri zmene objektu, ktor\u00fd ma dopad na serializ\u00e1ciu, by ste mali upravi\u0165 aj t\u00fato hodnotu. Ako presne, to u\u017e je na v\u00e1s. Pre Javu je podstatn\u00e9 len to, \u017ee to nebude rovnak\u00e1 hodnota. A to by bolo pre d\u00e1tov\u00fd objekt v\u0161etko. Takto pripraven\u00fd s\u00fabor u\u017e len sta\u010d\u00ed podhodi\u0165 predt\u00fdm spom\u00ednan\u00fdm triedam a malo by d\u00f4js\u0165 k serializ\u00e1cii.<\/span><\/p>\n<p><span style=\"font-style: normal;\">S predkami triedy to m\u00f4\u017ee by\u0165 ale trochu komplikovanej\u0161ie. Ako som p\u00edsal, tretia podmienka je, \u017ee by mal by\u0165 serializovate\u013en\u00fd aj predok. Nie v\u017edy sa to ale d\u00e1, a preto na to existuje rie\u0161enie. Podstatn\u00e9 je, aby mal predok bezparametrick\u00fd verejn\u00fd kon\u0161truktor. Java tak bude vedie\u0165 vytvori\u0165 objekt tak\u00e9ho typu, ale to e\u0161te neznamen\u00e1, \u017ee bude zapisova\u0165\/\u010d\u00edta\u0165 jeho premenn\u00e9. O to sa mus\u00edte postara\u0165 vy v odvodenej triede. Ako som p\u00edsal vy\u0161\u0161ie, Serializable v podstate neobsahuje \u017eiadne povinn\u00e9 met\u00f3dy. To \u201ev podstate\u201c som pou\u017eil preto, \u017ee m\u00e1 ak\u00fasi podporu pre dve met\u00f3dy, a to <\/span><em>writeObject(ObjectOuputStream in)<\/em><span style=\"font-style: normal;\"> a <\/span><em>readObject(ObjectInputStream out)<\/em><span style=\"font-style: normal;\">. S\u00fa to private met\u00f3dy a teda nejde tak \u00faplne o \u0161tandardn\u00fa implement\u00e1ciu rozhrania, ale pokia\u013e ich do svojej triedy zap\u00ed\u0161ete, bud\u00fa volan\u00e9. Pomocou t\u00fdchto met\u00f3d potom viete zap\u00edsa\u0165 \u00fadaje predkov do pr\u00fadu.<\/span><\/p>\n<p><span style=\"font-style: normal;\">Tieto dve spom\u00ednan\u00e9 met\u00f3dy s\u00fa tie\u017e k\u013e\u00fa\u010dom k vlastnej serializ\u00e1cii. To je ten pr\u00edpad, kedy sa rozhodnete prebra\u0165 riadenie serializ\u00e1cie do vlastn\u00fdch r\u00fak a namiesto toho, aby ste jednotliv\u00e9 premenn\u00e9 nechali Javu zapisova\u0165 sam\u00fa, pou\u017e\u00edvate met\u00f3dy ako <\/span><em>readBoolean() <\/em><span style=\"font-style: normal;\">a <\/span><em>readFloat()<\/em><span style=\"font-style: normal;\"> a ich opaky ako <\/span><em>writeBoolean()<\/em><span style=\"font-style: normal;\"> a <\/span><em>writeFloat()<\/em><span style=\"font-style: normal;\"> na zapisovanie jednotliv\u00fdch \u00fadajov. Takto ste schopn\u00ed sa rozhodn\u00fa\u0165, ktor\u00e9 premenn\u00e9 a v akom porad\u00ed bud\u00fa zap\u00edsan\u00e9.<\/span><\/p>\n<p><span style=\"font-style: normal;\">Ak sa na chv\u00ed\u013eu vr\u00e1tim k nat\u00edvnej serializ\u00e1cii, tak je tu e\u0161te jedna kr\u00e1tka t\u00e9ma. Predstavte si, \u017ee nechcete, aby bola nejak\u00e1 premenn\u00e1 serializovan\u00e1. Ako to dosiahnete? Existuje na to magick\u00fd modifik\u00e1tor <\/span><em>transient,<\/em><span style=\"font-style: normal;\"> ktor\u00fdm mus\u00edte dan\u00fa premenn\u00fa ozna\u010di\u0165. N\u00e1sledne ju Java bude pova\u017eova\u0165 za behov\u00fa\/do\u010dasn\u00fa inform\u00e1ciu a nebude ju ani zapisova\u0165, ani \u010d\u00edta\u0165.<\/span><\/p>\n<p><span style=\"font-style: normal;\">\u010eal\u0161ia t\u00e9ma, na ktor\u00fa treba pri serializ\u00e1cii myslie\u0165 je, \u017ee pri \u010d\u00edtan\u00ed pomocou met\u00f3dy <\/span><em>ObjectInputStream.readObject()<\/em><span style=\"font-style: normal;\"> dost\u00e1vate odkaz na objektu typu <\/span><em>Object<\/em><span style=\"font-style: normal;\">. Vy ale potrebujete svoje dom\u00e9nov\u00e9 objekty, a preto mus\u00edte urobi\u0165 <\/span><span style=\"color: #000000;\"><span style=\"font-style: normal;\"><span style=\"background: transparent;\">pretypovanie<\/span><\/span><\/span><span style=\"font-style: normal;\">. V pr\u00edpade, \u017ee ste si ist\u00fd t\u00fdm, \u010do v\u00e1m pri deserializ\u00e1cii vypadne z tejto met\u00f3dy, m\u00f4\u017eete rovno pretypov\u00e1va\u0165. Ak ste v\u0161ak zap\u00edsali pole objektov r<\/span><span style=\"font-style: normal;\"><span style=\"background: transparent;\">\u00f4znych tried<\/span><\/span><span style=\"font-style: normal;\"> (pri\u010dom to pole bolo pole base objektov), tak to nemus\u00ed by\u0165 tak\u00e9 jednoduch\u00e9. V takom pr\u00edpade sa d\u00e1 pou\u017ei\u0165 oper\u00e1tor <\/span><em>instanceof<\/em><span style=\"font-style: normal;\"> alebo metoda <\/span><em>Class.GetName()<\/em><span style=\"font-style: normal;\"> na zistenie presn\u00e9ho typu a n\u00e1sledn\u00e9 pretypovanie objektu.<\/span><\/p>\n<p>Posledn\u00e1 \u0161pecialita serializ\u00e1cie je optimaliz\u00e1cia, ktor\u00e1 je \u0161tandardne pri z\u00e1pise zapnut\u00e1. T\u00e1to optimaliz\u00e1cia sp\u00f4sobuje, \u017ee ak raz serializujete jeden objekt, a potom ho chcete v jednom behu zaserializova\u0165 znova, pou\u017eije sa u\u017e pripraven\u00e1 prv\u00e1 verzia. A teda, ak ste medzit\u00fdm objekt zmenili, do s\u00faboru sa op\u00e4\u0165 zap\u00ed\u0161e jeho p\u00f4vodn\u00e1 verzia. Aby ste sa toho zbavili, mus\u00edte pred druh\u00fdm z\u00e1pisom vola\u0165 met\u00f3du <em>ObjectOutputStream.Reset()<\/em>. T\u00e1 sp\u00f4sob\u00ed, \u017ee sa pri druh\u00fd raz zap\u00ed\u0161e aktu\u00e1lna verzia objektu.<\/p>\n<p>Ako som p\u00edsal v \u00favode, serializ\u00e1cia je ve\u013emi be\u017en\u00fd probl\u00e9m a je dos\u0165 mo\u017en\u00e9, \u017ee sa s n\u00edm stretnete. Ak vynech\u00e1m \u0161tandardn\u00fd pr\u00edpad z\u00e1pisu do s\u00faboru, ve\u013emi \u010dasto sa pou\u017e\u00edva pri komunik\u00e1cii so sie\u0165ov\u00fdmi slu\u017ebami, kde sa objekty serializuj\u00fa do XML alebo JSON a takto sa pren\u00e1\u0161aj\u00fa po sieti pomocou niektor\u00e9ho protokolu na prenos s\u00faborov (s\u00fa to de-facto tie\u017e s\u00fabory ale nie ulo\u017een\u00e9 na disku). Aj preto v\u00e1m jej zvl\u00e1dnutie m\u00f4\u017ee u\u0161etri\u0165 mno\u017estvo pr\u00e1ce a boles\u0165 hlavy zo situ\u00e1cie, pri ktorej nerozumiete, ako k nej m\u00f4\u017ee doch\u00e1dza\u0165 (ako napr\u00edklad optimaliz\u00e1cia z posledn\u00e9ho odseku).<\/p>","protected":false},"excerpt":{"rendered":"<p>Pokia\u013e sa z\u00fa\u010dast\u0148ujete v\u00e4\u010d\u0161ieho projektu tak je mo\u017en\u00e9, \u017ee sk\u00f4r alebo nesk\u00f4r naraz\u00edte na probl\u00e9m, ktor\u00fd je ve\u013emi be\u017en\u00fd. Chcete serializova\u0165\/deserializova\u0165 objekty. Teda prev\u00e1dza\u0165 ich \u00fadaje v pam\u00e4ti na pr\u00fad bajtov (niekedy znakov) a to tak, aby ste ich v inom \u010dase alebo na inom mieste vedeli pre\u010d\u00edta\u0165 nasp\u00e4\u0165. Ako mnoh\u00e9 vyspel\u00e9 jazyky, aj Java [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[],"class_list":["post-40","post","type-post","status-publish","format-standard","hentry","category-vyvoj-softveru"],"_links":{"self":[{"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/posts\/40","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/comments?post=40"}],"version-history":[{"count":2,"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/posts\/40\/revisions"}],"predecessor-version":[{"id":203,"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/posts\/40\/revisions\/203"}],"wp:attachment":[{"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/media?parent=40"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/categories?post=40"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spireng.sk\/en\/wp-json\/wp\/v2\/tags?post=40"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}