Programiranje

Končni superrazred, 1. del

Izkušeni razvijalci Java pogosto jemljejo samoumevne funkcije Java, ki jih novince zmede. Na primer, začetnik je lahko zmeden glede Predmet razred. Ta objava predstavlja tridelno serijo, v kateri predstavljam in odgovarjam na vprašanja o Predmet in njegove metode.

King Predmet

V: Kaj je Predmet razred?

A: The Predmet razred, ki je shranjen v java.lang paket je končni superrazred vseh razredov Java (razen Predmet). Poleg tega se nizi razširijo Predmet. Vendar se vmesniki ne širijo Predmet, ki je poudarjeno v oddelku 9.6.3.4 Specifikacije jezika Java: ... upoštevajte, da medtem ko vmesnik nima Predmet kot nadtip ....

Predmet izjavlja o naslednjih metodah, o katerih bom v celoti razpravljal kasneje v tej objavi in ​​v nadaljevanju te serije:

  • klon zaščitenega predmeta ()
  • logično enako (objekt obj)
  • zaščitena praznina finalize ()
  • Razred getClass ()
  • int hashCode ()
  • obvestilo o ničnosti ()
  • void notifyAll ()
  • String toString ()
  • neveljavno čakanje ()
  • neveljavno čakanje (dolga časovna omejitev)
  • neveljavno čakanje (dolga časovna omejitev, int nanos)

Razred Java podeduje te metode in lahko preglasi katero koli metodo, ki ni deklarirana dokončno. Na primerdokončnotoString () je mogoče preglasiti, medtem ko dokončnopočakaj () metod ni mogoče preglasiti.

V: Ali lahko izrecno razširim Predmet razred?

A: Da, izrecno lahko podaljšate Predmet. Na primer, preverite seznam 1.

Seznam 1. Izrecno se širi Predmet

uvoz java.lang.Object; javni razred Employee razširi Object {private String name; javni zaposleni (ime niza) {this.name = ime; } javni niz getName () {return ime; } public static void main (String [] args) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}

Seznam 1 lahko sestavite (javac zaposleni.java) in zaženite nastalo Zaposleni.razred mapa (java zaposleni), in opazovali boste John Doe kot izhod.

Ker prevajalnik samodejno uvozi tipe iz java.lang paket, uvoz java.lang.Object; izjava ni potrebna. Java vas tudi ne prisili, da izrecno razširjate Predmet. Če bi se, ne bi mogli podaljšati nobenega drugega razreda kot Predmet ker Java omejuje razširitev razreda na en razred. Zato bi običajno podaljšali Predmet implicitno, kot je prikazano v seznamu 2.

Seznam 2. Implicitno razširitev Predmet

javni razred Zaposlen {ime zasebnega niza; javni zaposleni (ime niza) {this.name = ime; } javni niz getName () {return ime; } public static void main (String [] args) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}

Tako kot na seznamu 1, tudi na seznamu 2 Zaposleni razred se razširi Predmet in podeduje njegove metode.

Kloniranje predmetov

V: Kaj pomeni klon () metoda izpolniti?

A: The klon () metoda ustvari in vrne kopijo predmeta, v katerem je ta metoda poklicana.

V: Kako klon () metoda dela?

A:Predmet izvaja klon () kot izvorna metoda, kar pomeni, da je njena koda shranjena v izvorni knjižnici. Ko se ta koda izvede, preveri razred (ali nadrazred) predmeta, ki prikliče, da ugotovi, ali izvaja java.lang.Cloneable vmesnik - Predmet se ne izvaja Klonirano. Če ta vmesnik ni izveden, klon () meti java.lang.CloneNotSupportedException, ki je preverjena izjema (z njo je treba ravnati ali ji prenašati niz klica metode tako, da se v glavo metode doda klavzula throws klon () je bil poklican). Če je ta vmesnik izveden, klon () dodeli nov objekt in kopira vrednosti polj kličočega predmeta v enakovredna polja novega predmeta in vrne sklic na novi objekt.

V: Kako prikličem datoteko klon () metoda za kloniranje predmeta?

A: Glede na sklic na objekt, pokličite klon () na tej referenci in vrnite vrnjeni predmet iz Predmet glede na tip predmeta, ki se klonira. Seznam 3 predstavlja primer.

Seznam 3. Kloniranje predmeta

javni razred CloneDemo izvaja Cloneable {int x; public static void main (String [] args) vrže CloneNotSupportedException {CloneDemo cd = new CloneDemo (); cd.x = 5; System.out.printf ("cd.x =% d% n", cd.x); CloneDemo cd2 = (CloneDemo) cd.clone (); System.out.printf ("cd2.x =% d% n", cd2.x); }}

Seznam 3 navaja a CloneDemo razred, ki izvaja Klonirano vmesnik. Ta vmesnik mora biti izveden ali priklic Predmetje klon () metoda bo povzročila vržen CloneNotSupportedException primer.

CloneDemo razglasi en sam int-imenovano polje primerka x in a glavni () metoda, ki izvaja ta razred. glavni () je razglašen s klavzulo o metanju, ki preide CloneNotSupportedException navzgor po klicu metode.

glavni () prvi primerki CloneDemo in inicializira nastalo kopijo primerka x do 5. Nato izpiše primerke x vrednost in prikliče klon () v tem primeru vrne vrnjeni predmet v CloneDemo preden shranite sklic. Končno izpiše klonove x vrednost polja.

Sestavi seznam 3 (javac CloneDemo.java) in zaženite aplikacijo (java CloneDemo). Upoštevati morate naslednje rezultate:

cd.x = 5 cd2.x = 5

V: Zakaj bi moral preglasiti klon () metoda?

A: Prejšnjemu primeru ni bilo treba preglasiti klon () metoda, ker koda, ki prikliče klon () se nahaja v razredu, ki se klonira (tj. CloneDemo razred). Če pa klon () klic se nahaja v drugem razredu, boste morali preglasiti klon (). V nasprotnem primeru boste prejeli "klon je zaščitil dostop v objektu"sporočilo, ker klon () je razglašena zaščiten. Seznam 4 predstavlja preoblikovan seznam 3, da dokaže razveljavitev klon ().

Seznam 4. Kloniranje predmeta iz drugega razreda

razred Data implementira Cloneable {int x; @Override public Object clone () vrže CloneNotSupportedException {return super.clone (); }} javni razred CloneDemo {public static void main (String [] args) vrže CloneNotSupportedException {Data data = new Data (); data.x = 5; System.out.printf ("data.x =% d% n", data.x); Podatki data2 = (Data) data.clone (); System.out.printf ("data2.x =% d% n", data2.x); }}

Seznam 4 navaja a Podatki razred, katerega primerke je treba klonirati. Ta razred izvaja Klonirano vmesnik za preprečevanje CloneNotSupportedException pred metanjem, ko klon () metoda se prikaže, izjavi intpolje na osnovi primerka x, in preglasi klon () metoda. Ta metoda se izvaja super.clone () sklicevati se na svoj superrazred (Predmetv tem primeru) klon () metoda. Prevladujoče klon () metoda identificira CloneNotSupportedException v klavzuli o metu.

Seznam 4 navaja tudi a CloneDemo razred, ki ustvari primerek Podatki, inicializira svoje polje primerka, prikaže vrednost polja primerka tega primera, klonira Podatki in izpiše vrednost polja primerka tega primerka.

Sestavi seznam 4 (javac CloneDemo.java) in zaženite aplikacijo (java CloneDemo). Upoštevati morate naslednje rezultate:

data.x = 5 data2.x = 5

V: Kaj je plitvo kloniranje?

A:Plitvo kloniranje (poznan tudi kot plitvo kopiranje) je podvajanje polj predmeta brez podvajanja predmetov, na katere se sklicujejo referenčna polja predmeta (če jih ima). Navedbe 3 in 4 kažejo plitvo kloniranje. Vsak od cd-, cd2-, podatkov-, in podatki2-referencirana polja identificirajo objekt, ki ima svojo kopijo int-temelji x polje.

Plitvo kloniranje dobro deluje, če so vsa polja prvotnega tipa in (v mnogih primerih), kadar se sklicujejo katera koli referenčna polja nespremenljiv (nespremenljivi) predmeti. Če pa je kateri koli predmet, na katerega se sklicuje, spremenljiv, lahko prvotni predmet in njegovi kloni (-i) vidijo spremembe, ki jih naredi kateri koli od teh predmetov. Seznam 5 predstavlja predstavitev.

Seznam 5. Prikaz težave s plitvim kloniranjem v kontekstu referenčnega polja

class Zaposleni izvaja Cloneable {private String name; zasebna int starost; naslov zasebnega naslova; Zaposleni (Ime niza, starost, naslov, naslov) {this.name = ime; this.age = starost; this.address = naslov; } @Override public Object clone () vrže CloneNotSupportedException {return super.clone (); } Naslov getAddress () {povratni naslov; } String getName () {return ime; } int getAge () {vrnitev starosti; }} naslov naslova {private String city; Naslov (niz mesta) {this.city = city; } String getCity () {return city; } void setCity (String city) {this.city = city; }} javni razred CloneDemo {public static void main (String [] args) vrže CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, nov naslov ("Denver")); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); Zaposlen e2 = (Zaposlen) e.clone (); System.out.printf ("% s:% d:% s% n", e2.getName (), e2.getAge (), e2.getAddress (). GetCity ()); e.getAddress (). setCity ("Chicago"); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); System.out.printf ("% s:% d:% s% n", e2.getName (), e2.getAge (), e2.getAddress (). GetCity ()); }}

Seznam 5 predstavlja Zaposleni, Naslov, in CloneDemo razredih. Zaposleni izjavlja ime, starost, in naslov polja; in ga je mogoče klonirati. Naslov razglasi naslov mesta, katerega primeri so spremenljivi. CloneDemo poganja aplikacijo.

CloneDemoje glavni () metoda ustvari Zaposleni objekt in ga klonira. Nato spremeni ime mesta v izvirniku Zaposleni predmeta naslov polje. Ker oboje Zaposleni predmeti se sklicujejo na isto Naslov objekt, spremenjeno mesto vidijo oba predmeta.

Sestavi seznam 5 (javac CloneDemo.java) in zaženite to aplikacijo (java CloneDemo). Upoštevati morate naslednje rezultate:

John Doe: 49: Denver John Doe: 49: Denver John Doe: 49: Chicago John Doe: 49: Chicago

V: Kaj je globoko kloniranje?

A:Globoko kloniranje (poznan tudi kot globoko kopiranje) je podvajanje polj predmeta tako, da se podvojijo vsi referenčni predmeti. Poleg tega se njihovi referenčni predmeti podvajajo - in tako naprej. Na primer, seznam 6 preoblikuje seznam 5, da izkoristi globoko kloniranje. Prav tako prikazuje kovariantne vrste vrnitve in prožnejši način kloniranja.

Seznam 6. Globoko kloniranje naslov polje

class Zaposleni izvaja Cloneable {private String name; zasebna int starost; naslov zasebnega naslova; Zaposleni (Ime niza, starost, naslov, naslov) {this.name = ime; this.age = starost; this.address = naslov; } @Override public Employee clone () vrže CloneNotSupportedException {Employee e = (Employee) super.clone (); e.address = address.clone (); vrnitev e; } Naslov getAddress () {povratni naslov; } String getName () {return ime; } int getAge () {vrnitev starosti; }} naslov naslova {private String city; Naslov (niz mesta) {this.city = city; } @Override javni naslov clone () {vrni nov naslov (nov niz (mesto)); } String getCity () {return city; } void setCity (String city) {this.city = city; }} javni razred CloneDemo {public static void main (String [] args) vrže CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, nov naslov ("Denver")); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); Zaposlen e2 = (Zaposlen) e.clone (); System.out.printf ("% s:% d:% s% n", e2.getName (), e2.getAge (), e2.getAddress (). GetCity ()); e.getAddress (). setCity ("Chicago"); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); System.out.printf ("% s:% d:% s% n", e2.getName (), e2.getAge (), e2.getAddress (). GetCity ()); }}

Navedba 6 izkorišča podporo Jave za kovarijantne vrste vrnitve za spremembo vrste vrnitve Zaposleniprevlada klon () metoda iz Predmet do Zaposleni. Prednost je v zunanji kodi Zaposleni lahko klonira Zaposleni predmeta, ne da bi ga bilo treba oddati v Zaposleni tip.

Zaposlenije klon () metoda najprej prikliče super.clone (), ki plitko kopira ime, starost, in naslov polja. Nato se prikliče klon () na naslov polje, da naredite dvojnik sklica Naslov predmet.

The Naslov razred preglasi klon () metoda in razkrije nekaj razlik od prejšnjih razredov, ki preglasijo to metodo:

  • Naslov se ne izvaja Klonirano. Ni nujno, ker samo Predmetje klon () metoda zahteva, da razred izvaja ta vmesnik in to klon () metoda ni poklicana.
  • Prevladujoče klon () metoda ne vrže CloneNotSupportedException. Ta preverjena izjema je vržena samo iz Predmetje klon () metoda, ki se ne imenuje. Zato izjeme ni treba obdelati ali ji poslati mimo klica metode prek klavzule throws.
  • Predmetje klon () metoda ni poklicana (ni super.clone () klic), ker plitko kopiranje za Naslov razred - kopirate lahko samo eno polje.

Za kloniranje Naslov predmeta, zadostuje ustvariti novega Naslov in ga inicializirajte v dvojnik predmeta, na katerega se sklicuje datoteka mesto polje. Novi Naslov predmet se nato vrne.

$config[zx-auto] not found$config[zx-overlay] not found