Programovanie

Najvyššia nadtrieda, 1. časť

Skúsení vývojári v odbore Java často považujú za samozrejmé funkcie Java, ktoré sú pre nováčikov mätúce. Napríklad začiatočník môže byť z toho zmätený Objekt trieda. Tento príspevok uvádza na trh trojdielnu sériu, v ktorej uvádzam a odpovedám na otázky Objekt a jeho metódy.

Kráľ Object

Otázka: Čo je Objekt trieda?

A: The Objekt triedy, ktorá je uložená v java.lang balíček, je najvyššou nadtriedou všetkých tried Java (okrem Objekt). Polia sa tiež rozširujú Objekt. Rozhrania sa však nerozširujú Objekt, na ktorú upozorňuje oddiel 9.6.3.4 špecifikácie jazyka Java: ... zvážte, že zatiaľ čo rozhranie nemá Objekt ako supertyp ....

Objekt deklaruje nasledujúce metódy, ktorým sa budem podrobnejšie venovať ďalej v tomto príspevku a vo zvyšku tejto série:

  • klon chráneného objektu ()
  • boolean equals (Object obj)
  • chránená prázdnota finalize ()
  • Trieda getClass ()
  • int hashCode ()
  • void notify ()
  • void notifyAll ()
  • String toString ()
  • neplatné čakanie ()
  • neplatné čakanie (dlhý časový limit)
  • void wait (long timeout, int nanos)

Trieda Java dedí tieto metódy a môže prepísať každú metódu, ktorá nie je deklarovaná konečné. Napríkladkonečnénatiahnuť() metóda môže byť prepísaná, zatiaľ čo konečnépočkaj () metódy nemožno prepísať.

Otázka: Môžem výslovne rozšíriť Objekt trieda?

A: Áno, môžete to výslovne predĺžiť Objekt. Napríklad, pozrite si zoznam 1.

Výpis 1. Výslovne sa rozširuje Objekt

import java.lang.Object; public class Zamestnanec rozširuje Object {private String name; public Employee (String name) {this.name = name; } public String getName () {návratové meno; } public static void main (String [] args) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}

Môžete zostaviť záznam 1 (javac Employee.java) a výsledný výsledok spustite Zamestnanec.trieda spis (java zamestnanec), a budete pozorovať John Doe ako výstup.

Pretože kompilátor automaticky importuje typy z java.lang balíček, import java.lang.Object; vyhlásenie je zbytočné. Java vás tiež nenúti výslovne rozširovať Objekt. Ak by to tak bolo, nemohli by ste rozšíriť iné triedy ako Objekt pretože Java obmedzuje rozšírenie triedy na jednu triedu. Preto by ste zvyčajne predĺžili Objekt implicitne, ako je uvedené v zozname 2.

Zoznam 2. Implicitne sa rozširuje Objekt

public class Employee {private String name; public Employee (String name) {this.name = name; } public String getName () {návratové meno; } public static void main (String [] args) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}

Rovnako ako v zozname 1, zozname 2 Zamestnanec trieda predlžuje Objekt a dedí svoje metódy.

Klonovanie predmetov

Otázka: Čo robí klon () metóda splniť?

A: The klon () metóda vytvorí a vráti kópiu objektu, na ktorom sa táto metóda volá.

Otázka: Ako to robí klon () metóda práce?

A:Objekt náradie klon () ako natívna metóda, čo znamená, že jej kód je uložený v natívnej knižnici. Keď sa tento kód spustí, skontroluje triedu (alebo nadtriedu) vyvolávajúceho objektu, aby zistil, či implementuje java.lang.Obnoviteľné rozhranie -- Objekt nerealizuje Cloneable. Ak toto rozhranie nie je implementované, klon () hodí java.lang.CloneNotSupportedException, čo je kontrolovaná výnimka (musí sa s ňou manipulovať alebo ju odovzdať do zásobníka volaní metód pridaním klauzuly throws k hlavičke metódy, v ktorej klon () bol vyvolaný). Ak je toto rozhranie implementované, klon () pridelí nový objekt a skopíruje hodnoty polí volajúceho objektu do ekvivalentných polí nového objektu a vráti odkaz na nový objekt.

Otázka: Ako sa môžem dovolať klon () metóda na klonovanie objektu?

A: Vzhľadom na odkaz na objekt, vyvolajte klon () na tento odkaz a vrhnúť vrátený objekt z Objekt podľa typu klonovaného objektu. Výpis 3 predstavuje príklad.

Zoznam 3. Klonovanie objektu

verejná trieda CloneDemo implementuje Cloneable {int x; public static void main (String [] args) hodí 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); }}

Zoznam 3 vyhlasuje a CloneDemo trieda, ktorá implementuje Cloneable rozhranie. Toto rozhranie musí byť implementované alebo musí byť vyvolané Objektje klon () metóda bude mať za následok vyhodenie CloneNotSupportedException inštancia.

CloneDemo vyhlasuje za slobodného int- pomenované pole inštancie X a a hlavný() metóda, ktorá túto hodinu precvičuje. hlavný() je deklarovaná pomocou klauzuly hodov, ktorá prechádza CloneNotSupportedException do zásobníka metódových volaní.

hlavný() prvé inštancie CloneDemo a inicializuje kópiu výslednej inštancie X do 5. Potom vydá výstupy inštancie X hodnotu a vyvoláva klon () v tomto prípade casting vráteného objektu na CloneDemo pred uložením jeho referencie. Nakoniec vydá klon X hodnota poľa.

Zostaviť zoznam 3 (javac CloneDemo.java) a spustite aplikáciu (java CloneDemo). Mali by ste dodržiavať nasledujúci výstup:

cd.x = 5 cd2.x = 5

Otázka: Prečo by som musel prepísať klon () metóda?

A: Predchádzajúci príklad nemusel prepísať klon () metóda, pretože kód, ktorý vyvoláva klon () sa nachádza v triede, ktorá sa klonuje (t. j CloneDemo trieda). Ak však klon () vyvolanie sa nachádza v inej triede, budete musieť prepísať klon (). V opačnom prípade dostaneteklon má chránený prístup v objekte„správa, pretože klon () je vyhlásený chránené. Zoznam 4 predstavuje prepracovaný zoznam 3, ktorý demonštruje prepísanie klon ().

Výpis 4. Klonovanie objektu z inej triedy

trieda Dátové implementácie Cloneable {int x; @Override public Object clone () hodí CloneNotSupportedException {return super.clone (); }} public class CloneDemo {public static void main (String [] args) hodí CloneNotSupportedException {Data data = new Data (); data.x = 5; System.out.printf ("data.x =% d% n", data.x); Data data2 = (Data) data.clone (); System.out.printf ("data2.x =% d% n", data2.x); }}

Výpis 4 deklaruje a Údaje triedy, ktorej inštancie sa majú klonovať. Táto trieda implementuje Cloneable rozhranie zabrániť CloneNotSupportedException pred vyhodením, keď klon () metóda sa volá, deklaruje int- inštančné pole Xa prepíše klon () metóda. Táto metóda sa vykoná super.clone () vyvolať svoju nadtriedu (Objektv tomto príklade) klon () metóda. Naliehavé klon () metóda identifikuje CloneNotSupportedException v klauzule jeho hodov.

Zoznam 4 tiež deklaruje a CloneDemo trieda, ktorá vytvára inštancie Údaje, inicializuje svoje inštančné pole, odošle hodnotu tohto inštančného poľa, klonuje Údaje inštancia a na výstup privádza hodnotu poľa inštancie tejto inštancie.

Zostaviť zoznam 4 (javac CloneDemo.java) a spustite aplikáciu (java CloneDemo). Mali by ste dodržiavať nasledujúci výstup:

data.x = 5 data2.x = 5

Otázka: Čo je plytké klonovanie?

A:Plytké klonovanie (taktiež známy ako plytké kopírovanie) je duplikácia polí objektu bez duplikovania akýchkoľvek objektov, na ktoré sa odkazuje z referenčných polí objektu (ak existuje). Výpisy 3 a 4 demonštrujú povrchné klonovanie. Každá z cd-, cd2-, údaje- a data2-referencované polia identifikujú objekt, ktorý má svoju vlastnú kópiu int- na základe X lúka.

Plytké klonovanie funguje dobre, keď sú všetky polia primitívneho typu a (v mnohých prípadoch), keď sa na ne odkazuje nejaké referenčné pole nemenný (nemeniteľné) predmety. Ak sú však niektoré odkazované objekty zmeniteľné, pôvodný objekt a jeho klon (y) môžu vidieť zmeny vykonané v ktoromkoľvek z týchto objektov. Zoznam 5 predstavuje demonštráciu.

Zoznam 5. Preukázanie problému s plytkým klonovaním v kontexte referenčného poľa

trieda Zamestnanec implementuje Cloneable {private String name; súkromný int vek; adresa súkromnej adresy; Zamestnanec (meno reťazca, vek, adresa) {this.name = meno; this.age = vek; this.address = adresa; } @Override public Object clone () hodí CloneNotSupportedException {return super.clone (); } Adresa getAddress () {spiatočná adresa; } Reťazec getName () {návratové meno; } int getAge () {návratový vek; }} trieda Adresa {private String city; Adresa (reťazec mesto) {this.city = city; } String getCity () {return city; } void setCity (String city) {this.city = city; }} public class CloneDemo {public static void main (String [] args) throws CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, new Address ("Denver")); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); Zamestnanec e2 = (zamestnanec) 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 ()); }}

Zoznam 5 darčekov Zamestnanec, Adresaa CloneDemo triedy. Zamestnanec vyhlasuje názov, Veka adresa polia; a je klonovateľný. Adresa vyhlasuje, že adresa pozostávajúca z mesta a jeho inštancií je premenlivá. CloneDemo riadi aplikáciu.

CloneDemoje hlavný() metóda vytvára Zamestnanec objekt a klonuje tento objekt. Potom sa zmení pôvodný názov mesta Zamestnanec objektu adresa lúka. Pretože oboje Zamestnanec objekty odkazujú rovnako Adresa objekt, zmenené mesto vidia oba objekty.

Zostaviť zoznam 5 (javac CloneDemo.java) a spustite túto aplikáciu (java CloneDemo). Mali by ste dodržiavať nasledujúci výstup:

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

Otázka: Čo je hlboké klonovanie?

A:Hlboké klonovanie (taktiež známy ako hlboké kopírovanie) je duplikácia polí objektu tak, aby boli duplikované všetky odkazované objekty. Ďalej sú ich odkazované objekty duplikované - a tak ďalej. Napríklad zoznam 6 refaktorov uvedených v zozname 5 na využitie hlbokého klonovania. Ukazuje tiež typy kovariančných návratov a flexibilnejší spôsob klonovania.

Zoznam 6. Hlboké klonovanie adresa lúka

trieda Zamestnanec implementuje Cloneable {private String name; súkromný int vek; adresa súkromnej adresy; Zamestnanec (meno reťazca, vek, adresa) {this.name = meno; this.age = vek; this.address = adresa; } @Override public Employee clone () hodí CloneNotSupportedException {Employee e = (Employee) super.clone (); e.adresa = adresa.klon (); návrat e; } Adresa getAddress () {spiatočná adresa; } Reťazec getName () {návratové meno; } int getAge () {návratový vek; }} trieda Adresa {private String city; Adresa (reťazec mesto) {this.city = city; } @Override public Address clone () {return new Address (new String (city)); } String getCity () {return city; } void setCity (String city) {this.city = city; }} public class CloneDemo {public static void main (String [] args) throws CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, new Address ("Denver")); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); Zamestnanec e2 = (zamestnanec) 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 ()); }}

Zoznam 6 využíva podporu Javy pre kovariantné návratové typy na zmenu návratového typu Zamestnanecje prvoradý klon () metóda z Objekt do Zamestnanec. Výhodou je, že externý kód je Zamestnanec môže klonovať Zamestnanec objekt bez toho, aby ste tento objekt museli odovzdať Zamestnanec typu.

Zamestnanecje klon () metóda najskôr vyvolá super.clone (), ktorý povrchne kopíruje názov, Veka adresa polia. Potom sa vyvolá klon () na adresa pole na vytvorenie duplikátu referencovaného Adresa objekt.

The Adresa trieda prepíše klon () metóda a odhaľuje niekoľko rozdielov od predchádzajúcich tried, ktoré túto metódu prepisujú:

  • Adresa nerealizuje Cloneable. Nie je to potrebné, pretože iba Objektje klon () metóda vyžaduje, aby trieda implementovala toto rozhranie a toto klon () metóda sa nevolá.
  • Naliehavé klon () metóda nehádže CloneNotSupportedException. Táto zaškrtnutá výnimka je vyvolaná iba z Objektje klon () metóda, ktorá sa nevolá. Výnimka preto nemusí byť spracovaná alebo odovzdaná do zásobníka volaní metód cez klauzulu throws.
  • Objektje klon () metóda sa nevolá (nie je super.clone () volanie), pretože plynulé kopírovanie sa nevyžaduje pre Adresa trieda - existuje iba jedno pole na kopírovanie.

Klonovať Adresa objekt, stačí vytvoriť nový Adresa objekt a inicializujte ho na duplikát objektu odkazovaného z mesto lúka. Nové Adresa objekt sa potom vráti.

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