Patyrę „Java“ kūrėjai dažnai laiko savaime suprantamomis „Java“ funkcijomis, kurios naujokams atrodo painios. Pavyzdžiui, pradedantysis gali būti supainiotas dėl Objektas
klasė. Šiuo pranešimu pradedama trijų dalių serija, kurioje pristatau ir atsakau į klausimus Objektas
ir jos metodai.
Karaliaus objektas
Klausimas: Kas yra Objektas
klasė?
A: Objektas
klasė, kuri saugoma java.lang
paketas yra pagrindinis visų „Java“ klasių (išskyrus Objektas
). Be to, masyvai tęsiasi Objektas
. Tačiau sąsajos nesitęsia Objektas
, kuris nurodytas „Java“ kalbos specifikacijos 9.6.3.4 skirsnyje: ... mano, kad nors sąsaja neturi Objektas
kaip supertipas ....
Objektas
deklaruoja šiuos metodus, kuriuos aš išsamiai aptarsiu vėliau šiame įraše ir likusioje šios serijos dalyje:
saugomas objekto klonas ()
loginė lygi (Object obj)
apsaugotas negaliojantis baigti ()
Klasė „getClass“ ()
int hashCode ()
negaliojantis pranešimas ()
negalioja praneštiVisi ()
Stygos toString ()
tuščias laukimas ()
tuščias laukimas (ilgas skirtasis laikas)
tuščias laukimas (ilgas skirtasis laikas, int nanos)
„Java“ klasė paveldi šiuos metodus ir gali nepaisyti bet kurio nedeklaruoto metodo galutinis
. Pavyzdžiui,galutinis
toString ()
metodas gali būti nepaisomas, o galutinis
laukti()
metodų negalima nepaisyti.
Klausimas: Ar galiu aiškiai pratęsti Objektas
klasė?
A: Taip, galite aiškiai pratęsti Objektas
. Pavyzdžiui, peržiūrėkite 1 sąrašą.
Išvardinimas 1. Aiškiai pratęsiama Objektas
importuoti java.lang.Object; viešoji klasė Darbuotojas praplečia objektą {privatus eilutės pavadinimas; viešasis darbuotojas (eilutės pavadinimas) {this.name = vardas; } public String getName () {grąžinimo vardas; } public static void main (String [] args) {Darbuotojo emp = naujas darbuotojas ("John Doe"); System.out.println (emp.getName ()); }}
Galite sudaryti 1 sąrašą (javac Employee.java
) ir paleiskite gautą rezultatą Darbuotojas.klasė
failas (java darbuotojas
), ir jūs pastebėsite Jonas Doe
kaip išvestis.
Kadangi kompiliatorius automatiškai importuoja tipus iš java.lang
paketas, importuoti java.lang.Object;
pareiškimas nereikalingas. Be to, „Java“ neverčia jūsų aiškiai išplėsti Objektas
. Jei taip būtų, negalėtumėte pratęsti jokių kitų klasių, išskyrus Objektas
nes „Java“ riboja klasės pratęsimą iki vienos klasės. Todėl paprastai pratęsiate Objektas
netiesiogiai, kaip parodyta 2 sąraše.
Sąrašas 2. Netiesiogiai pratęsiantis Objektas
viešoji klasė Darbuotojas {privatus Stygos vardas; viešasis darbuotojas (eilutės pavadinimas) {this.name = vardas; } public String getName () {grąžinimo vardas; } public static void main (String [] args) {Darbuotojo emp = naujas darbuotojas ("John Doe"); System.out.println (emp.getName ()); }}
Kaip ir 1 sąraše, 2 sąraše Darbuotojas
klasė tęsiasi Objektas
ir paveldi jos metodus.
Objektų klonavimas
Klausimas: Ką daro klonas ()
metodas pasiekti?
A: klonas ()
metodas sukuria ir grąžina objekto, kuriam vadinamas šis metodas, kopiją.
Klausimas: Kaip veikia klonas ()
metodo darbas?
A:Objektas
padargai klonas ()
kaip vietinį metodą, o tai reiškia, kad jo kodas saugomas gimtojoje bibliotekoje. Kai šis kodas vykdomas, jis patikrina iškviečiančio objekto klasę (arba superklasę), ar jis įgyvendina java.lang. Klonuojamas
sąsaja - Objektas
neįgyvendina Klonuojamas
. Jei ši sąsaja neįdiegta, klonas ()
metimai java.lang.CloneNotSupportedException
, kuri yra pažymėta išimtis (ji turi būti tvarkoma arba perkeliama į metod-call kaminą, prie metodo, kuriame naudojamas metodas, antraštėje pridedant metimų sąlygą klonas ()
buvo pasitelktas). Jei ši sąsaja įdiegta, klonas ()
priskiria naują objektą ir nukopijuoja iškviečiamo objekto lauko vertes į naujus objekto lygiaverčius laukus ir grąžina nuorodą į naują objektą.
Klausimas: Kaip aš galiu pasinaudoti klonas ()
metodas klonuoti objektą?
A: Atsižvelgiant į objekto nuorodą, iškvieskite klonas ()
ant šios nuorodos ir išmeskite grąžintą objektą iš Objektas
į klonuojamo objekto tipą. 3 sąrašas pateikia pavyzdį.
Sąrašas 3. Objekto klonavimas
viešoji klasė „CloneDemo“ įgyvendina „Cloneable“ {int x; public static void main (String [] args) meta CloneNotSupportedException {CloneDemo cd = new CloneDemo (); cdx = 5; System.out.printf ("cd.x =% d% n", cd.x); CloneDemo cd2 = (CloneDemo) cd. klonas (); System.out.printf ("cd2.x =% d% n", cd2.x); }}
3 sąraše skelbiama a „CloneDemo“
klasė, kuri įgyvendina Klonuojamas
sąsaja. Ši sąsaja turi būti įdiegta arba iškviesta Objektas
's klonas ()
metodas lems mesti CloneNotSupportedException
instancija.
„CloneDemo“
deklaruoja vienintelį tarpt
pavadintas egzemplioriaus laukas x
ir a pagrindinis ()
metodas, pratęsiantis šią klasę. pagrindinis ()
yra deklaruojamas su metimo sąlyga, kuri praeina CloneNotSupportedException
pakelti metodo skambučio kaminą.
pagrindinis ()
pirmiausia akimirksniu „CloneDemo“
ir inicijuoja gautos egzemplioriaus kopiją x
į 5
. Tada jis išleidžia egzempliorius x
vertę ir remiasi klonas ()
šiuo atveju grąžinamo objekto liejimas į „CloneDemo“
prieš saugodamas nuorodą. Galiausiai, jis išleidžia klono x
lauko vertė.
Sudaryti 3 sąrašą (javac CloneDemo.java
) ir paleiskite programą (java CloneDemo
). Turėtumėte stebėti šį rezultatą:
cd.x = 5 cd2.x = 5
Klausimas: Kodėl turėčiau nepaisyti klonas ()
metodas?
A: Ankstesniam pavyzdžiui nereikėjo nepaisyti klonas ()
metodas, nes kodas, kuris iškviečia klonas ()
yra klonuojamoje klasėje (t. y „CloneDemo“
klasė). Tačiau jei klonas ()
iškvietimas yra kitoje klasėje, turėsite nepaisyti klonas ()
. Priešingu atveju gausite „klonas apsaugojo prieigą objekte
"pranešimas, nes klonas ()
yra deklaruojamas saugomi
. 4 sąraše pateikiamas atnaujintas 3 sąrašas, siekiant parodyti svarbesnį klonas ()
.
Sąrašas 4. Klonuoti objektą iš kitos klasės
klasės duomenys įgyvendinami Cloneable {int x; @Override public Object clone () meta CloneNotSupportedException {return super.clone (); }} public class CloneDemo {public static void main (String [] args) meta CloneNotSupportedException {Data data = new Data (); duomenys.x = 5; System.out.printf ("duomenys.x =% d% n", duomenys.x); Duomenų duomenys2 = (Duomenys) duomenys.klonas (); System.out.printf ("duomenys2.x =% d% n", duomenys2.x); }}
4 sąraše skelbiama a Duomenys
klasės, kurios egzemplioriai turi būti klonuojami. Ši klasė įgyvendina Klonuojamas
sąsaja užkirsti kelią CloneNotSupportedException
nuo metimo, kai klonas ()
metodas vadinamas, deklaruoja tarpt
pagrįstas egzemplioriaus laukas x
ir nepaiso klonas ()
metodas. Šis metodas vykdomas super.klonas ()
pasinaudoti savo superklasės (Objektas
šiame pavyzdyje) klonas ()
metodas. Svarbiausia klonas ()
metodas identifikuoja CloneNotSupportedException
savo metimų sąlyga.
4 sąraše taip pat skelbiama a „CloneDemo“
klasė, kuri momentuoja Duomenys
, inicializuoja jo egzemplioriaus lauką, pateikia šio egzemplioriaus lauko vertę, klonuoja Duomenys
egzempliorių ir pateikia šio egzemplioriaus lauko reikšmę.
Sudaryti 4 sąrašą (javac CloneDemo.java
) ir paleiskite programą (java CloneDemo
). Turėtumėte stebėti šį rezultatą:
duomenys.x = 5 duomenys2.x = 5
Klausimas: Kas yra negilus klonavimas?
A:Negilus klonavimas (taip pat žinomas kaip seklus kopijavimas) yra objekto laukų kopija, nedubliuojant jokių objektų, į kuriuos yra nuoroda iš objekto nuorodų laukų (jei tokių yra). 3 ir 4 sąrašai rodo seklų klonavimą. Kiekvienas iš cd
-, cd2
-, duomenis
- ir duomenys2
nurodomi laukai identifikuoja objektą, kuris turi savo tarpt
-pagrįstas x
srityje.
Negilus klonavimas veikia gerai, kai visi laukai yra primityvaus tipo ir (daugeliu atvejų), kai nurodomi bet kurie nuorodų laukai nekintamas (nekeičiami) objektai. Tačiau, jei kuris nors nurodytas objektas yra kintamas, bet kurio iš šių objektų pakeitimus gali pamatyti originalus objektas ir jo klonas (-ai). 5 sąraše pateikiama demonstracija.
Sąrašas 5. Sekliojo klonavimo problemos parodymas atskaitos lauko kontekste
klasė Darbuotojas įgyvendina Cloneable {private String name; privatus int amžius; asmeninis adreso adresas; Darbuotojas (eilutės pavadinimas, int amžius, adreso adresas) {this.name = vardas; tai. amžius = amžius; tai.adresas = adresas; } @Paisyti viešojo objekto kloną () meta CloneNotSupportedException {return super.clone (); } Adresas getAddress () {grąžinimo adresas; } String getName () {grąžinimo vardas; } int getAge () {grįžimo amžius; }} klasės adresas {private String city; Adresas (styginis miestas) {this.city = miestas; } String getCity () {grįžimo miestas; } void setCity (Styginių miestas) {this.city = miestas; }} public class CloneDemo {public static void main (String [] args) meta CloneNotSupportedException {Employee e = naujas darbuotojas ("John Doe", 49, naujas adresas ("Denver")); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); Darbuotojas e2 = (Darbuotojas) e.klonas (); System.out.printf ("% s:% d:% s% n", e2.getName (), e2.getAge (), e2.getAddress (). GetCity ()); e.getAddress (). setCity („Čikaga“); 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 ()); }}
Išvardijamos 5 dovanos Darbuotojas
, Adresas
ir „CloneDemo“
klasės. Darbuotojas
pareiškia vardas
, amžiaus
ir adresas
laukai; ir yra klonuojamas. Adresas
deklaruoja adresą, susidedantį iš miesto, o jo egzemplioriai yra kintami. „CloneDemo“
varo programą.
„CloneDemo“
's pagrindinis ()
metodas sukuria Darbuotojas
objektą ir klonuoja šį objektą. Tada jis keičia miesto pavadinimą originalu Darbuotojas
objekto adresas
srityje. Nes abu Darbuotojas
objektai nurodo tą patį Adresas
objektą, pakeistą miestą mato abu objektai.
Sudaryti 5 sąrašą (javac CloneDemo.java
) ir paleiskite šią programą (java CloneDemo
). Turėtumėte stebėti šį rezultatą:
John Doe: 49: Denveris John Doe: 49: Denveris John Doe: 49: Chicago John Doe: 49: Chicago
Klausimas: Kas yra gilus klonavimas?
A:Gilus klonavimas (taip pat žinomas kaip gilus kopijavimas) yra objekto laukų dublikatas, kad visi nurodyti objektai būtų dubliuojami. Be to, jų nurodyti objektai yra dubliuojami ir pan. Pavyzdžiui, 6 refaktorių sąrašas „5“ sąrašas, skirtas giliam klonavimui. Tai taip pat parodo kovariantinius grąžinimo tipus ir lankstesnį klonavimo būdą.
Sąrašas 6. Gilus klonavimas adresas
srityje
klasė Darbuotojas įgyvendina Cloneable {private String name; privatus int amžius; asmeninis adreso adresas; Darbuotojas (eilutės pavadinimas, int amžius, adreso adresas) {this.name = vardas; tai. amžius = amžius; tai.adresas = adresas; } @Paisyti viešąjį darbuotojų kloną () išmeta CloneNotSupportedException {Darbuotojo e = (Darbuotojas) super.klonas (); el. adresas = adresas.klonas (); grįžti e; } Adresas getAddress () {grąžinimo adresas; } String getName () {grąžinimo vardas; } int getAge () {grįžimo amžius; }} klasės adresas {private String city; Adresas (styginis miestas) {this.city = miestas; } @Paisyti viešojo adreso kloną () {grąžinti naują adresą (nauja eilutė (miestas)); } String getCity () {grįžimo miestas; } void setCity (Styginių miestas) {this.city = miestas; }} public class CloneDemo {public static void main (String [] args) meta CloneNotSupportedException {Employee e = naujas darbuotojas ("John Doe", 49, naujas adresas ("Denver")); System.out.printf ("% s:% d:% s% n", e.getName (), e.getAge (), e.getAddress (). GetCity ()); Darbuotojas e2 = (Darbuotojas) e.klonas (); System.out.printf ("% s:% d:% s% n", e2.getName (), e2.getAge (), e2.getAddress (). GetCity ()); e.getAddress (). setCity („Čikaga“); 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 ()); }}
6 sąrašas išnaudoja „Java“ paramą kovariantiniams grąžinimo tipams, kad pakeistų grąžinimo tipą Darbuotojas
yra svarbesnis klonas ()
metodas nuo Objektas
į Darbuotojas
. Privalumas yra tas, kad kodas yra išorinis Darbuotojas
gali klonuoti Darbuotojas
objekto nereikia mesti šio objekto į Darbuotojas
tipo.
Darbuotojas
's klonas ()
metodas pirmiausia remiasi super.klonas ()
, kuris negiliai kopijuoja vardas
, amžiaus
ir adresas
laukai. Tada jis pasikviečia klonas ()
ant adresas
lauką, kad padarytumėte nuorodos kopiją Adresas
objektas.
Adresas
klasė nepaiso klonas ()
metodas ir atskleidžia keletą skirtumų nuo ankstesnių klasių, kurios nepaiso šio metodo:
Adresas
neįgyvendinaKlonuojamas
. Tai nėra būtina, nes tikObjektas
'sklonas ()
metodas reikalauja, kad klasė įdiegtų šią sąsają, ir taiklonas ()
metodas nėra vadinamas.- Svarbiausia
klonas ()
metodas nemetaCloneNotSupportedException
. Ši pažymėta išimtis pateikiama tik išObjektas
'sklonas ()
metodas, kuris nėra vadinamas. Todėl išimtis neturi būti tvarkoma arba perkeliama į metod-call kaminą per metimo sąlygą. Objektas
'sklonas ()
metodas nėra vadinamas (nėrasuper.klonas ()
skambinti), nes sekti kopijuoti nereikiaAdresas
klasė - yra tik vienas laukas, kurį reikia nukopijuoti.
Klonuoti Adresas
objekto, pakanka sukurti naują Adresas
objektą ir inicializuokite jį į objekto, į kurį nurodoma, kopiją miestas
srityje. Nauja Adresas
objektas grąžinamas.