Programování

Dědičnost v Javě, Část 2: Objekt a jeho metody

Java poskytuje standardní knihovnu tříd skládající se z tisíců tříd a dalších referenčních typů. Navzdory rozdílům v jejich schopnostech tvoří tyto typy jednu masivní hierarchii dědičnosti přímým nebo nepřímým rozšířením Objekt třída. To platí také pro všechny třídy a další typy odkazů, které vytvoříte.

První polovina tohoto tutoriálu o dědičnosti Java vám ukázala základy dědičnosti, konkrétně jak používat Javurozšiřuje a super klíčová slova pro odvození podřízené třídy z nadřazené třídy, vyvolání konstruktorů a metod nadřazené třídy, přepsání metod atd. Nyní se zaměříme na mateřskou loď hierarchie dědičnosti tříd Java, java.lang.Object.

Studovat Objekt a jeho metody vám pomohou lépe porozumět dědičnosti a jejímu fungování ve vašich programech Java. Seznámení s těmito metodami vám obecně pomůže lépe pochopit programy Java.

stáhnout Získat kód Stáhněte si zdrojový kód například pro aplikace v tomto výukovém programu. Vytvořil Jeff Friesen pro JavaWorld.

Objekt: Java je nadtřída

Objekt je kořenová třída nebo konečná nadtřída všech ostatních tříd Java. Uloženo v java.lang balík, Objekt deklaruje následující metody, které zdědí všechny ostatní třídy:

  • klon chráněného objektu ()
  • boolean equals (Object obj)
  • chráněná prázdnota finalize ()
  • Třída getClass ()
  • int hashCode ()
  • zrušit upozornění ()
  • void notifyAll ()
  • String toString ()
  • void wait ()
  • neplatné čekání (dlouhý časový limit)
  • void wait (long timeout, int nanos)

Třída Java zdědí tyto metody a může přepsat jakoukoli metodu, která není deklarována finále. NapříkladfináletoString () metoda může být přepsána, zatímco finálePočkejte() metody nemohou.

Podíváme se na každou z těchto metod a na to, jak vám umožňují provádět speciální úkoly v kontextu vašich tříd Java. Nejprve se podívejme na základní pravidla a mechanismy pro Objekt dědictví.

Obecné typy

Ve výše uvedeném seznamu jste si možná všimli getClass (), jehož Třída návratový typ je příkladem a obecný typ. Obecným typům se budu věnovat v budoucím článku.

Rozšíření objektu: Příklad

Třída se může výslovně rozšířit Objekt, jak je uvedeno v seznamu 1.

Výpis 1. Explicitně rozšiřující objekt

public class Zaměstnanec rozšiřuje Object {private String name; public Employee (String name) {this.name = name; } public String getName () {zpáteční jméno; } public static void main (String [] args) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}

Protože můžete rozšířit maximálně jednu další třídu (připomeňme, že Java nepodporuje vícenásobné dědictví založené na třídách), nejste nuceni explicitně rozšířit Objekt; jinak byste nemohli rozšířit žádnou jinou třídu. Proto byste prodloužili Objekt implicitně, jak je uvedeno v seznamu 2.

Výpis 2. Implicitně rozšiřující objekt

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

Zkompilujte výpis 1 nebo výpis 2 následujícím způsobem:

javac Employee.java

Spusťte výslednou aplikaci:

java zaměstnanec

Měli byste dodržovat následující výstup:

John Doe

Další informace o třídě: getClass ()

The getClass () metoda vrací běhovou třídu libovolného objektu, na kterém je volána. The běhová třída je reprezentován a Třída objekt, který se nachází v java.lang balík. Třída je vstupním bodem do rozhraní Java Reflection API, o kterém se dozvíte, až se dostaneme k pokročilejším tématům v programování Java. Zatím víte, že aplikace Java používá Třída a zbytek Java Reflection API se dozvíte o jeho vlastní struktuře.

Objekty třídy a statické synchronizované metody

Vrátil se Třída objekt je objekt, který je uzamčen statická synchronizace metody představované třídy; například, statická synchronizovaná void foo () {}. (Synchronizaci Java představím v budoucím výukovém programu.)

Duplikování objektů: clone ()

The klon () metoda vytvoří a vrátí kopii objektu, na kterém je volána. Protože klon ()návratový typ je Objekt, odkaz na objekt klon () před přiřazením odkazu na proměnnou typu objektu musí být vráceny skutečnému typu objektu. Výpis 3 představuje aplikaci, která demonstruje klonování.

Výpis 3. Klonování objektu

třída CloneDemo implementuje Cloneable {int x; public static void main (String [] args) hodí CloneNotSupportedException {CloneDemo cd = new CloneDemo (); cd.x = 5; System.out.println ("cd.x =" + cd.x); CloneDemo cd2 = (CloneDemo) cd.clone (); System.out.println ("cd2.x =" + cd2.x); }}

Výpis 3 CloneDemo třída implementuje Cloneable rozhraní, které se nachází v java.lang balík. Cloneable je implementována třídou (prostřednictvím nářadí klíčové slovo) Objektje klon () metoda z házení instance CloneNotSupportedException třída (také nalezena v java.lang).

CloneDemo deklaruje singl int- pojmenované pole instance X a hlavní() metoda, která tuto třídu procvičuje. hlavní() je deklarováno s hodí klauzule, která prochází CloneNotSupportedException nahoru zásobník volání metod.

hlavní() první instance CloneDemo a inicializuje kopii výsledné instance X na 5. Potom vydá instance X hodnota a volání klon () v tomto případě casting vráceného objektu do CloneDemo před uložením jeho reference. Nakonec vydá klon X hodnota pole.

Zkompilovat výpis 3 (javac CloneDemo.java) a spusťte aplikaci (java CloneDemo). Měli byste dodržovat následující výstup:

cd.x = 5 cd2.x = 5

Přepsat klon ()

Předchozí příklad nepotřeboval přepsat klon () protože kód, který volá klon () se nachází v klonované třídě (CloneDemo). Pokud volání na klon () byly umístěny v jiné třídě, pak byste museli přepsat klon (). Protože klon () je deklarováno chráněný, obdržíte „klon má chráněný přístup v Object"zpráva, pokud jste ji před kompilací třídy nepotlačili. Výpis 4 představuje refaktorovaný výpis 3, který ukazuje přepsání klon ().

Výpis 4. Klonování objektu z jiné třídy

třída Data implementuje Cloneable {int x; @Override public Object clone () hodí CloneNotSupportedException {návrat super.clone (); }} třída CloneDemo {public static void main (String [] args) hodí CloneNotSupportedException {Data data = new Data (); data.x = 5; System.out.println ("data.x =" + data.x); Data data2 = (Data) data.clone (); System.out.println ("data2.x =" + data2.x); }}

Výpis 4 deklaruje a Data třída, jejíž instance mají být klonovány. Data realizuje Cloneable rozhraní, aby se zabránilo a CloneNotSupportedException před hozením, když klon () metoda se nazývá. Poté prohlásí int-založené pole instance Xa přepíše klon () metoda. The klon () metoda se provede super.clone () volat jeho nadtřídu (tj. Objekt's) klon () metoda. Naléhavé klon () metoda identifikuje CloneNotSupportedException v jeho hodí doložka.

Výpis 4 také deklaruje a CloneDemo třída, která: vytváří instanci Data, inicializuje své pole instance, vypíše hodnotu pole instance, naklonuje Data objekt a na výstupu zobrazí jeho hodnotu pole instance.

Zkompilovat výpis 4 (javac CloneDemo.java) a spusťte aplikaci (java CloneDemo). Měli byste dodržovat následující výstup:

data.x = 5 data2.x = 5

Mělké klonování

Mělké klonování (také známý jako mělké kopírování) odkazuje na duplikování polí objektu bez duplikování jakýchkoli objektů, na které se odkazuje z referenčních polí daného objektu (pokud existují nějaká referenční pole). Výpisy 3 a 4 skutečně prokázaly mělké klonování. Každý z CD-, cd2-, data-, a data2-referencovaná pole označuje objekt, který má vlastní kopii int-na základě X pole.

Mělké klonování funguje dobře, když jsou všechna pole primitivního typu a (v mnoha případech), když se na ně odkazují některá referenční pole neměnný (neměnné) objekty. Pokud jsou však libovolné odkazované objekty proměnlivé, změny provedené v kterémkoli z těchto objektů lze vidět podle původního objektu a jeho klonů. Výpis 5 ukazuje.

Výpis 5. Problém s mělkým klonováním v kontextu referenčního pole

třída Zaměstnanec implementuje Cloneable {private String name; soukromý věk; adresa soukromé adresy; Zaměstnanec (jméno řetězce, stáří, adresa) {this.name = name; this.age = věk; this.address = adresa; } @Override public Object clone () hodí CloneNotSupportedException {návrat super.clone (); } Adresa getAddress () {zpáteční adresa; } Řetězec getName () {návratové jméno; } int getAge () {návratový věk; }} třída Adresa {soukromé město řetězce; Adresa (řetězec město) {this.city = city; } String getCity () {návratové město; } void setCity (String city) {this.city = city; }} třída CloneDemo {public static void main (String [] args) hodí CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, new Address ("Denver")); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); Zaměstnanec e2 = (zaměstnanec) e.clone (); System.out.println (e2.getName () + ":" + e2.getAge () + ":" + e2.getAddress (). GetCity ()); e.getAddress (). setCity ("Chicago"); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); System.out.println (e2.getName () + ":" + e2.getAge () + ":" + e2.getAddress (). GetCity ()); }}

Seznam 5 dárků Zaměstnanec, Adresa, a CloneDemo třídy. Zaměstnanec prohlašuje název, stáří, a adresa pole; a je klonovatelný. Adresa prohlašuje, že adresa skládající se z města a jeho instancí je proměnlivá. CloneDemo řídí aplikaci.

CloneDemoje hlavní() metoda vytvoří Zaměstnanec objekt a klonuje tento objekt. Poté změní název města v originále Zaměstnanec objektu adresa pole. Protože obojí Zaměstnanec objekty odkazují stejně Adresa objekt, oba objekty vidí změněné město.

Zkompilovat výpis 5 (javac CloneDemo.java) a spusťte tuto aplikaci (java CloneDemo). Měli byste dodržovat následující výstup:

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

Hluboké klonování

Hluboké klonování (také známý jako hluboké kopírování) odkazuje na duplikování polí objektu tak, aby byly duplikovány všechny odkazované objekty. Dále jsou duplikovány odkazované objekty odkazovaných objektů atd. Výpis 6 refaktorů Výpis 5 k prokázání hlubokého klonování.

Výpis 6. Hluboké klonování pole adresy

třída Zaměstnanec implementuje Cloneable {private String name; soukromý věk; adresa soukromé adresy; Zaměstnanec (jméno řetězce, stáří, adresa) {this.name = name; this.age = věk; this.address = adresa; } @Override public Object clone () hodí CloneNotSupportedException {Employee e = (Employee) super.clone (); e.adresa = (adresa) address.clone (); návrat e; } Adresa getAddress () {zpáteční adresa; } Řetězec getName () {návratové jméno; } int getAge () {návratový věk; }} třída Adresa {soukromé město řetězce; Adresa (řetězec město) {this.city = city; } @Override public Object clone () {return new Address (new String (city)); } String getCity () {návratové město; } void setCity (String city) {this.city = city; }} třída CloneDemo {public static void main (String [] args) hodí CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, new Address ("Denver")); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); Zaměstnanec e2 = (zaměstnanec) e.clone (); System.out.println (e2.getName () + ":" + e2.getAge () + ":" + e2.getAddress (). GetCity ()); e.getAddress (). setCity ("Chicago"); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); System.out.println (e2.getName () + ":" + e2.getAge () + ":" + e2.getAddress (). GetCity ()); }}

Výpis 6 to ukazuje Zaměstnanecje klon () metoda první volání super.clone (), který mělce kopíruje název, stáří, a adresa pole. Pak zavolá klon () na adresa pole pro vytvoření duplikátu odkazovaného Adresa objekt. Adresa přepíše klon () metoda a odhaluje několik rozdílů od předchozích tříd, které tuto metodu přepíší:

  • Adresa neprovádí Cloneable. Není to nutné, protože jen Objektje klon () metoda vyžaduje, aby třída implementovala toto rozhraní a toto klon () metoda není volána.
  • Naléhavé klon () metoda nehází CloneNotSupportedException. Tato výjimka je vyvolána pouze z Objektje klon () metoda, která se nevolá. Proto výjimka nemusí být zpracována nebo předána do zásobníku volání metody pomocí klauzule throws.
  • Objektje klon () metoda se nevolá (není super.clone () volání), protože pro Adresa třída - ke kopírování existuje pouze jedno pole.
$config[zx-auto] not found$config[zx-overlay] not found