Java tarjoaa tavallisen luokkakirjaston, joka koostuu tuhansista luokista ja muista viitetyypeistä. Hyvyydestään eroavaisuudesta huolimatta nämä tyypit muodostavat yhden massiivisen perintöhierarkian laajentamalla suoraan tai epäsuorasti Esine
luokassa. Tämä pätee myös luomaasi luokkaan ja muuhun viitetyyppiin.
Tämän Java-perinnön opetusohjelman alkupuoliskolla saatiin esille perinnön perusteet ja erityisesti Java-ohjelmien käyttöulottuu
ja super
avainsanat, joilla johdetaan lapsiluokka vanhempien luokasta, vedetään vanhempien luokan rakentajiin ja menetelmiin, ohitetaan menetelmiä ja muuta. Nyt keskitymme Java-luokan perintöhierarkian emolevyyn, java.lang.objekti
.
Opiskelu Esine
ja sen menetelmät auttavat sinua saamaan toiminnallisemman käsityksen perinnöstä ja siitä, miten se toimii Java-ohjelmissasi. Noiden menetelmien tuntemus auttaa ymmärtämään Java-ohjelmia yleensä.
Kohde: Java: n superluokka
Esine
on kaikkien muiden Java-luokkien juuriluokka tai perimmäinen superluokka. Tallennettu java.lang
paketti, Esine
julistaa seuraavat menetelmät, jotka kaikki muut luokat perivät:
suojattu objektiklooni ()
looginen arvo on yhtä suuri (Object obj)
suojattu void viimeistele ()
Luokka getClass ()
int hashCode ()
mitätön ilmoitus ()
mitätön ilmoitusAll ()
Merkkijono merkkijonolle ()
mitätöi odota ()
mitätön odotus (pitkä aikakatkaisu)
mitätön odotus (pitkä aikakatkaisu, int nanos)
Java-luokka perii nämä menetelmät ja voi ohittaa minkä tahansa menetelmän, jota ei ole ilmoitettu lopullinen
. Esimerkiksi ei-lopullinen
toString ()
menetelmä voidaan ohittaa, kun taas lopullinen
odota()
menetelmät eivät voi.
Tarkastelemme kaikkia näitä menetelmiä ja miten niiden avulla voit suorittaa erityistehtäviä Java-luokkiesi yhteydessä. Tarkastellaan ensin perussääntöjä ja -mekanismeja Esine
perintö.
Yleiset tyypit
Olet ehkä huomannut yllä olevassa luettelossa getClass ()
, jonka Luokka
palautustyyppi on esimerkki a yleinen tyyppi. Keskustelen yleisistä tyypeistä tulevassa artikkelissa.
Objektin laajentaminen: Esimerkki
Luokka voi nimenomaisesti laajentaa Esine
, kuten luettelo 1 osoittaa.
Listaus 1. Objektin nimenomainen laajentaminen
public class Työntekijä laajentaa Object {private String name; public Employee (String name) {tämä.nimi = nimi; } public String getName () {palautusnimi; } public static void main (Merkkijono [] argumentti) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}
Koska voit laajentaa enintään yhtä muuta luokkaa (muista osasta 1, että Java ei tue luokkaperusteista useita perintöjä), et ole pakko nimenomaisesti laajentaa Esine
; muuten et voinut laajentaa mitään muuta luokkaa. Siksi jatkaisit Esine
epäsuorasti, kuten luettelo 2 osoittaa.
Listaus 2. Objektin implisiittisesti laajentaminen
julkinen luokka Työntekijä {yksityinen String nimi; julkinen työntekijä (merkkijono) {tämä.nimi = nimi; } public String getName () {palautusnimi; } public static void main (Merkkijono [] argumentti) {Employee emp = new Employee ("John Doe"); System.out.println (emp.getName ()); }}
Koosta Listing 1 tai Listing 2 seuraavasti:
javac Employee.java
Suorita tuloksena oleva sovellus:
java Työntekijä
Ota huomioon seuraava tulos:
John Doe
Lisätietoja luokasta: getClass ()
getClass ()
method palauttaa minkä tahansa objektin ajon luokan, johon sitä kutsutaan. ajonaikainen luokka on a Luokka
esine, joka löytyy java.lang
paketti. Luokka
on lähtökohta Java Reflection -sovellusliittymään, josta opit, kun käsittelemme edistyneempiä aiheita Java-ohjelmoinnissa. Toistaiseksi tiedä, että Java-sovellus käyttää Luokka
ja loput Java Reflection -sovellusliittymästä oppiaksesi sen omasta rakenteesta.
Luokan objektit ja staattiset synkronoidut menetelmät
Palasi Luokka
objekti on lukittu objekti staattinen synkronoitu
edustetun luokan menetelmät; esimerkiksi, staattinen synkronoitu void foo () {}
. (Esittelen Java-synkronoinnin tulevassa opetusohjelmassa.)
Objektien kopiointi: klooni ()
klooni()
method luo ja palauttaa kopion objektista, johon sitä kutsutaan. Koska klooni()
Palautustyyppi on Esine
, objekti viittaa siihen klooni()
palautukset on lähetettävä objektin todelliseen tyyppiin, ennen kuin viittaus määritetään objektityypin muuttujalle. Listaus 3 esittää sovelluksen, joka osoittaa kloonauksen.
Listaus 3. Objektin kloonaus
luokka CloneDemo toteuttaa Cloneable {int x; public static void main (String [] args) heittää CloneNotSupportedException {CloneDemo cd = new CloneDemo (); cdx = 5; System.out.println ("cd.x =" + cd.x); CloneDemo cd2 = (CloneDemo) cd. klooni (); System.out.println ("cd2.x =" + cd2.x); }}
Luettelo 3: sta Kloonidemo
luokka toteuttaa Kloonattava
käyttöliittymä, joka löytyy java.lang
paketti. Kloonattava
luokan toteuttaa ( työvälineet
avainsana) estääksesi Esine
on klooni()
- tapa heittää CloneNotSupportedException
luokka (löytyy myös java.lang
).
Kloonidemo
julistaa yhden int
-perusteisen ilmentymän kentän nimi x
ja a main ()
menetelmä, joka harjoittaa tätä luokkaa. main ()
ilmoitetaan a: lla heittää
lauseke, joka kulkee CloneNotSupportedException
ylöspäin menetelmä-kutsupino.
main ()
ensin instantiates Kloonidemo
ja alustaa tuloksena olevan instanssin kopion x
että 5
. Sitten se tuottaa instanssin x
arvo ja puhelut klooni()
tässä tapauksessa palautetun objektin heittäminen kohteeseen Kloonidemo
ennen viitteen tallentamista. Lopuksi se tuottaa kloonin x
kentän arvo.
Koosta luettelo 3 (javac CloneDemo.java
) ja suorita sovellus (java CloneDemo
). Ota huomioon seuraava tulos:
cd.x = 5 cd2.x = 5
Korvaava klooni ()
Edellisen esimerkin ei tarvinnut ohittaa klooni()
koska koodi, joka kutsuu klooni()
sijaitsee kloonatussa luokassa (Kloonidemo
). Jos soitat klooni()
sijaitsivat kuitenkin toisessa luokassa, sinun pitäisi sitten ohittaa klooni()
. Koska klooni()
ilmoitetaan suojattu
, saisit "klooni on suojattu pääsy Object"-viesti, jos et ohittanut sitä ennen luokan kokoamista. Listaus 4 esittää uudistetun luettelon 3, joka osoittaa ohittavan klooni()
.
Listaus 4. Objektin kloonaus toisesta luokasta
luokka Datatyökalut Cloneable {int x; @Override public Object clone () heittää CloneNotSupportedException {return super.clone (); }} luokka CloneDemo {public static void main (String [] args) heittää CloneNotSupportedException {Data data = new Data (); data x = 5; System.out.println ("data.x =" + data.x); Data data2 = (data) data.klooni (); System.out.println ("data2.x =" + data2.x); }}
Listaus 4 ilmoittaa a Tiedot
luokka, jonka esiintymät on kloonattava. Tiedot
toteuttaa Kloonattava
käyttöliittymä estää a CloneNotSupportedException
heittämästä, kun klooni()
menetelmää kutsutaan. Sitten se julistaa int
-pohjainen instanssikenttä x
ja ohittaa klooni()
menetelmä. klooni()
menetelmä suoritetaan super.klooni ()
kutsua sen superluokkaa (eli Esine
n) klooni()
menetelmä. Ylivoimainen klooni()
menetelmä tunnistaa CloneNotSupportedException
sen heittää
lauseke.
Listaus 4 ilmoittaa myös a Kloonidemo
luokka, joka: instantizes Tiedot
, alustaa ilmentymäkentän, antaa ilmentymäkentän arvon, kloonaa Tiedot
objekti ja antaa sen ilmentymäkentän arvon.
Koosta luettelo 4 (javac CloneDemo.java
) ja suorita sovellus (java CloneDemo
). Ota huomioon seuraava tulos:
data.x = 5 data2.x = 5
Matala kloonaus
Matala kloonaus (tunnetaan myös matala kopiointi) viittaa objektin kenttien kopiointiin kopioimatta objekteja, joihin viitataan kyseisen objektin viitekentistä (jos referenssikenttiä on). Luettelot 3 ja 4 osoittivat todella matalan kloonauksen. Jokainen CD
-, cd2
-, tiedot
- ja tiedot 2
-viitekentät identifioivat objektin, jolla on oma kopio int
-perustuu x
ala.
Matala kloonaus toimii hyvin, kun kaikki kentät ovat primitiivisiä ja (monissa tapauksissa), kun viitekentät viittaavat muuttumaton (muuttumattomia) esineitä. Kuitenkin, jos jokin viitattu objekti on muutettavissa, alkuperäinen objekti ja sen klooni (t) näkevät mihin tahansa näistä kohteista tehdyt muutokset. Listaus 5 osoittaa.
Listaus 5. Matala kloonaus on ongelma viitekentän yhteydessä
luokka Työntekijä toteuttaa Cloneable {private String name; yksityinen ikä; yksityinen Osoite-osoite; Työntekijä (merkkijonon nimi, ikä, osoitteen osoite) {this.name = nimi; tämä. ikä = ikä; tämä.osoite = osoite; } @Override public Object clone () heittää CloneNotSupportedException {return super.clone (); } Osoite getAddress () {palautusosoite; } Merkkijono getName () {return name; } int getAge () {paluuikä; }} luokka Osoite {yksityinen Merkkijono kaupunki; Osoite (merkkijono kaupunki) {this.city = kaupunki; } String getCity () {paluukaupunki; } void setCity (merkkijono) {this.city = kaupunki; }} luokka CloneDemo {public static void main (String [] args) heittää CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, uusi osoite ("Denver")); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); Työntekijä e2 = (Työntekijä) e.klooni (); 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 ()); }}
Luettelossa 5 lahjaa Työntekijä
, Osoite
ja Kloonidemo
luokat. Työntekijä
julistaa nimi
, ikä
ja osoite
kentät; ja on kloonattava. Osoite
julistaa kaupungin muodostavan osoitteen ja sen esiintymät ovat muutettavissa. Kloonidemo
ajaa sovellusta.
Kloonidemo
on main ()
menetelmä luo Työntekijä
ja kloonaa tämän objektin. Sitten se muuttaa kaupungin nimen alkuperäisessä muodossa Työntekijä
esine osoite
ala. Koska molemmat Työntekijä
objektit viittaavat samaan Osoite
esine, molemmat kohteet näkevät muuttuneen kaupungin.
Koosta luettelo 5 (javac CloneDemo.java
) ja suorita tämä sovellus (java CloneDemo
). Ota huomioon seuraava tulos:
John Doe: 49: Denver John Doe: 49: Denver John Doe: 49: Chicago John Doe: 49: Chicago
Syvä kloonaus
Syvä kloonaus (tunnetaan myös syvä kopiointi) viittaa objektin kenttien kopiointiin siten, että kaikki viitatut objektit kopioidaan. Lisäksi viitattujen objektien viitatut objektit kopioidaan ja niin edelleen. Listaus 6 refaktoria Listaus 5 syvän kloonauksen osoittamiseksi.
Listaus 6. Osoitekentän syvä kloonaus
luokka Työntekijä toteuttaa Cloneable {private String name; yksityinen ikä; yksityinen Osoite-osoite; Työntekijä (merkkijonon nimi, ikä, osoitteen osoite) {this.name = nimi; tämä. ikä = ikä; tämä.osoite = osoite; } @Override public Object clone () heittää CloneNotSupportedException {Employee e = (Employee) super.clone (); e.osoite = (Osoite) osoite.klooni (); paluu e; } Osoite getAddress () {palautusosoite; } Merkkijono getName () {return name; } int getAge () {paluuikä; }} luokka Osoite {yksityinen Merkkijono kaupunki; Osoite (merkkijono kaupunki) {this.city = kaupunki; } @Override public Object clone () {return new Address (new String (city)); } String getCity () {paluukaupunki; } void setCity (merkkijono) {this.city = kaupunki; }} luokka CloneDemo {public static void main (String [] args) heittää CloneNotSupportedException {Employee e = new Employee ("John Doe", 49, uusi osoite ("Denver")); System.out.println (e.getName () + ":" + e.getAge () + ":" + e.getAddress (). GetCity ()); Työntekijä e2 = (Työntekijä) e.klooni (); 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 ()); }}
Listaus 6 osoittaa sen Työntekijä
on klooni()
menetelmä ensin kutsuu super.klooni ()
, joka kopioi matalasti nimi
, ikä
ja osoite
kentät. Sitten se soittaa klooni()
on osoite
-kenttään tehdäksesi kopion viitatusta Osoite
esine. Osoite
ohittaa klooni()
menetelmä ja paljastaa muutamia eroja aiempiin luokkiin, jotka ohittavat tämän menetelmän:
Osoite
ei toteutaKloonattava
. Se ei ole välttämätöntä, koska vainEsine
onklooni()
menetelmä edellyttää, että luokka toteuttaa tämän käyttöliittymän, ja tämäklooni()
menetelmää ei kutsuta.- Ylivoimainen
klooni()
menetelmä ei heitäCloneNotSupportedException
. Tämä poikkeus heitetään vainEsine
onklooni()
menetelmä, jota ei kutsuta. Siksi poikkeusta ei tarvitse käsitellä tai siirtää metod-call -pinoa heittolausekkeen kautta. Esine
onklooni()
menetelmää ei kutsuta (ei olesuper.klooni ()
puhelu), koska matalaa kopiointia ei vaaditaOsoite
luokka - kopioitavana on vain yksi kenttä.