Programmering

Arv i Java, del 2: Objekt og dets metoder

Java tilbyr et standard klassebibliotek bestående av tusenvis av klasser og andre referansetyper. Til tross for ulikheten i deres evner, utgjør disse typene ett massivt arvshierarki ved direkte eller indirekte å utvide Gjenstand klasse. Dette gjelder også for alle klasser og andre referansetyper du oppretter.

Første halvdel av denne veiledningen om Java-arv viste deg det grunnleggende om arv, spesielt hvordan du bruker Java-erstrekker og super nøkkelord for å utlede en underordnet klasse fra en overordnet klasse, påkalle foreldreklassekonstruktører og -metoder, overstyre metoder og mer. Nå vil vi rette fokus mot morsskipet til Java-klassens arvshierarki, java.lang.Objekt.

Studerer Gjenstand og dens metoder vil hjelpe deg med å få en mer funksjonell forståelse av arv og hvordan det fungerer i Java-programmene dine. Å være kjent med disse metodene vil hjelpe deg med å få større mening med Java-programmer, generelt.

last ned Få koden Last ned kildekoden for eksempel applikasjoner i denne opplæringen. Skapt av Jeff Friesen for JavaWorld.

Objekt: Java sin superklasse

Gjenstand er rotklassen, eller den ultimate superklassen, til alle andre Java-klasser. Lagret i java.lang pakke, Gjenstand erklærer følgende metoder, som alle andre klasser arver:

  • beskyttet objektklon ()
  • boolsk er lik (Objekt obj)
  • beskyttet tomrom fullføre ()
  • Klasse getClass ()
  • int hashCode ()
  • ugyldig beskjed ()
  • void notifyAll ()
  • String toString ()
  • ugyldig vent ()
  • ugyldig ventetid (lang tidsavbrudd)
  • ugyldig ventetid (lang tidsavbrudd, int nanoer)

En Java-klasse arver disse metodene og kan overstyre enhver metode som ikke er deklarert endelig. For eksempel den ikke-endeligtoString () metoden kan overstyres, mens endeligvente() metoder kan ikke.

Vi ser på hver av disse metodene og hvordan de gjør det mulig for deg å utføre spesielle oppgaver i sammenheng med Java-klassene dine. La oss først vurdere grunnleggende regler og mekanismer for Gjenstand arv.

Generiske typer

I listen ovenfor har du kanskje lagt merke til det getClass (), hvem sin Klasse returtype er et eksempel på en generisk type. Jeg vil diskutere generiske typer i en fremtidig artikkel.

Extending Object: Et eksempel

En klasse kan eksplisitt utvides Gjenstand, som vist i Listing 1.

Oppføring 1. Eksplisitt utvidende objekt

offentlig klasse Ansatt utvider Objekt {privat Strengnavn; offentlig ansatt (strengnavn) {this.name = navn; } public String getName () {return name; } public static void main (String [] args) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}

Fordi du maksimalt kan utvide en annen klasse (husk fra del 1 at Java ikke støtter klassebasert flerarv), blir du ikke tvunget til å eksplisitt utvide Gjenstand; Ellers kunne du ikke utvide noen annen klasse. Derfor vil du utvide Gjenstand implisitt, som vist i liste 2.

Oppføring 2. Implisitt utvider objektet

offentlig klasse Ansatt {privat strengnavn; offentlig ansatt (strengnavn) {this.name = navn; } public String getName () {return name; } public static void main (String [] args) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}

Kompiler liste 1 eller liste 2 som følger:

javac Ansatt.java

Kjør den resulterende applikasjonen:

java Ansatt

Du bør følge følgende utdata:

John Doe

Finn ut om en klasse: getClass ()

De getClass () metoden returnerer kjøretidsklassen til ethvert objekt den kalles på. De kjøretidsklasse er representert av en Klasse gjenstand, som finnes i java.lang pakke. Klasse er inngangspunktet til Java Reflection API, som du lærer om når vi kommer inn på mer avanserte emner innen Java-programmering. For nå, vet at et Java-program bruker Klasse og resten av Java Reflection API for å lære om sin egen struktur.

Klasseobjekter og statiske synkroniserte metoder

De returnerte Klasse objekt er objektet som er låst av statisk synkronisert metoder for den representerte klassen; for eksempel, statisk synkronisert ugyldig foo () {}. (Jeg introduserer Java-synkronisering i en fremtidig opplæring.)

Dupliserende objekter: klone ()

De klone () metoden oppretter og returnerer en kopi av objektet som det heter. Fordi klone ()Returtype er Gjenstand, objektet refererer til det klone () returneringer må kastes til objektets faktiske type før referansen tildeles en variabel av objektets type. Listing 3 presenterer et program som demonstrerer kloning.

Oppføring 3. Kloning av et objekt

klasse CloneDemo implementerer Cloneable {int x; public static void main (String [] args) kaster 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); }}

Listing 3's CloneDemo klasse implementerer Klonbar grensesnitt, som finnes i java.lang pakke. Klonbar er implementert av klassen (via redskaper nøkkelord) for å forhindre Gjenstands klone () metoden fra å kaste en forekomst av CloneNotSupportedException klasse (også funnet i java.lang).

CloneDemo erklærer en singel int-basert forekomstfelt navngitt x og en hoved() metode som utøver denne klassen. hoved() blir erklært med en kaster klausul som passerer CloneNotSupportedException opp metoden-samtalestakken.

hoved() første øyeblikkelig CloneDemo og initialiserer den resulterende forekomstens kopi av x til 5. Den sender deretter forekomsten ut x verdi og samtaler klone () i dette tilfellet å kaste det returnerte objektet til CloneDemo før du lagrer referansen. Til slutt gir den ut klonens x feltverdi.

Kompilere oppføring 3 (javac CloneDemo.java) og kjør applikasjonen (java CloneDemo). Du bør følge følgende utdata:

cd.x = 5 cd2.x = 5

Overstyrende klon ()

Det forrige eksemplet trengte ikke å overstyre klone () fordi koden som ringer klone () ligger i klassen som klones (CloneDemo). Hvis samtalen til klone () var plassert i en annen klasse, men da må du overstyre klone (). Fordi klone () blir erklært beskyttet, vil du motta en "klon har beskyttet tilgang i Object"melding hvis du ikke overstyrte den før du kompilerte klassen. Oppføring 4 presenterer en refaktorert oppføring 3 som viser overstyring klone ().

Oppføring 4. Kloning av et objekt fra en annen klasse

klasse Data implementerer Cloneable {int x; @ Override public Object-klon () kaster CloneNotSupportedException {return super.clone (); }} klasse CloneDemo {public static void main (String [] args) kaster 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); }}

Oppføring 4 erklærer a Data klasse hvis forekomster skal klones. Data implementerer Klonbar grensesnitt for å forhindre a CloneNotSupportedException fra å bli kastet når klone () metoden kalles. Det erklærer da int-basert forekomstfelt x, og overstyrer klone () metode. De klone () metoden kjøres super.clone () å kalle superklassen sin (det vil si Gjenstand's) klone () metode. Det overordnede klone () metoden identifiserer CloneNotSupportedException i sin kaster klausul.

Oppføring 4 erklærer også a CloneDemo klasse som: instantiates Data, initialiserer forekomstfeltet, sender ut verdien av forekomsten, kloner Data objektet, og sender ut sin forekomstfeltverdi.

Kompilere oppføring 4 (javac CloneDemo.java) og kjør applikasjonen (java CloneDemo). Du bør følge følgende utdata:

data.x = 5 data2.x = 5

Grunn kloning

Grunn kloning (også kjent som grunne kopiering) refererer til å duplisere et objekts felt uten å duplisere objekter som det refereres til fra objektets referansefelt (hvis det er noen referansefelt). Listing 3 og 4 demonstrerte faktisk grunne kloning. Hver av cd-, cd2-, data-, og data2-henviste felt identifiserer et objekt som har sin egen kopi av int-basert x felt.

Grunn kloning fungerer bra når alle felt er av primitiv type og (i mange tilfeller) når noen referansefelt refererer til uforanderlig (uforanderlige) gjenstander. Imidlertid, hvis noen refererte objekter er mutable, kan endringer som er gjort på et av disse objektene sees av det opprinnelige objektet og dets klon (er). Oppføring 5 viser.

Oppføring 5. Problemet med grunne kloning i en referansefeltkontekst

klasse Ansatt implementerer Cloneable {private String name; privat alder; privat adresse adresse; Ansatt (strengnavn, alder, adresseadresse) {this.name = navn; this.age = alder; denne.adressen = adresse; } @Override public Object clone () kaster CloneNotSupportedException {return super.clone (); } Adresse getAddress () {returadresse; } String getName () {return name; } int getAge () {retur alder; }} klasse Adresse {privat strengby; Adresse (strengby) {this.city = by; } String getCity () {retur by; } ugyldig setCity (strengby) {this.city = by; }} klasse CloneDemo {public static void main (String [] args) kaster CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, new Address ("Denver")); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); Ansatt e2 = (Ansatt) 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 ()); }}

Oppføring 5 gaver Ansatt, Adresse, og CloneDemo klasser. Ansatt erklærer Navn, alder, og adresse Enger; og er klonbar. Adresse erklærer en adresse som består av en by og dens forekomster er foranderlige. CloneDemo driver applikasjonen.

CloneDemos hoved() metoden skaper en Ansatt objekt og kloner dette objektet. Det endrer deretter byens navn i originalen Ansatt objektets adresse felt. Fordi begge deler Ansatt objekter refererer til det samme Adresse objekt, blir den forandrede byen sett av begge objektene.

Kompilere oppføring 5 (javac CloneDemo.java) og kjør dette programmet (java CloneDemo). Du bør følge følgende utdata:

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

Dyp kloning

Dyp kloning (også kjent som dyp kopiering) refererer til å duplisere et objekts felt slik at eventuelle refererte objekter dupliseres. Videre dupliseres de refererte objektene til refererte objekter, og så videre. Listing 6 refactors Listing 5 for å demonstrere dyp kloning.

Oppføring 6. Dyp kloning av adressefeltet

klasse Ansatt implementerer Cloneable {private String name; privat alder; privat adresse adresse; Ansatt (strengnavn, alder, adresseadresse) {this.name = navn; this.age = alder; denne.adressen = adresse; } @ Override public Object-klon () kaster CloneNotSupportedException {ansatt e = (ansatt) super.clone (); e.adresse = (Adresse) adresse.klone (); returnere e; } Adresse getAddress () {returadresse; } String getName () {return name; } int getAge () {retur alder; }} klasse Adresse {privat strengby; Adresse (strengby) {this.city = by; } @ Override public Object clone () {return new Address (new String (city)); } String getCity () {retur by; } ugyldig setCity (strengby) {this.city = by; }} klasse CloneDemo {public static void main (String [] args) kaster CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, new Address ("Denver")); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); Ansatt e2 = (Ansatt) 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 ()); }}

Oppføring 6 viser at Ansatts klone () metoden første samtaler super.clone (), som grunt kopierer Navn, alder, og adresse Enger. Det kaller da klone ()adresse felt for å lage en duplikat av den refererte Adresse gjenstand. Adresse overstyrer klone () metode og avslører noen forskjeller fra tidligere klasser som overstyrer denne metoden:

  • Adresse implementerer ikke Klonbar. Det er ikke nødvendig fordi bare Gjenstands klone () metoden krever at en klasse implementerer dette grensesnittet, og dette klone () metoden blir ikke kalt.
  • Det overordnede klone () metoden kaster ikke CloneNotSupportedException. Dette unntaket kastes bare fra Gjenstands klone () metoden, som ikke kalles. Derfor trenger ikke unntaket å håndteres eller sendes opp metoden-samtalestakken via en kast-klausul.
  • Gjenstands klone () metoden kalles ikke (det er ingen super.clone () kall) fordi grunne kopiering ikke er påkrevd for Adresse klasse - det er bare et enkelt felt å kopiere.
$config[zx-auto] not found$config[zx-overlay] not found