Programavimas

Ar „Java“ praeina pagal nuorodą, ar perduoda vertę?

Daugelis programavimo kalbų leidžia perduoti parametrus pagal nuorodą arba pagal vertę. „Java“ sistemoje galime perduoti tik parametrus pagal vertę. Tai nustato tam tikras ribas ir kelia klausimų. Pavyzdžiui, jei metodo parametro vertė yra pakeista, kas atsitiks su verte atlikus metodo vykdymą? Taip pat galite pasidomėti, kaip „Java“ valdo objektų reikšmes atminties kaupe. Tai „Java Challenger“ padeda išspręsti šiuos ir kitus dažniausiai pasitaikančius klausimus apie „Java“ objektų nuorodas.

Gaukite šaltinio kodą

Gaukite šio „Java Challenger“ kodą. Jūs galite atlikti savo testus, kol laikysitės pavyzdžių.

Objektų nuorodos perduodamos pagal vertę

Visos „Java“ objektų nuorodos perduodamos pagal vertę. Tai reiškia, kad vertės kopija bus perduota metodui. Tačiau apgaulė yra ta, kad perduodant vertės kopiją keičiama ir tikroji objekto vertė. Norėdami suprasti, kodėl, pradėkite nuo šio pavyzdžio:

 public class ObjectReferenceExample {public static void main (String ... doYourBest) {Simpson simpson = new Simpson (); transformIntoHomer (simpsonas); System.out.println (simpson.name); } static void transformIntoHomer (Simpson simpson) {simpson.name = "Homeras"; }} klasė Simpsonas {Stygos pavadinimas; } 

Ką manai simpson.name bus po „transformIntoHomer“ metodas yra vykdomas?

Šiuo atveju tai bus Homeras! Priežastis ta, kad „Java“ objektų kintamieji yra tiesiog nuorodos, nukreipiančios į tikrus atminties kaupo objektus. Todėl, net jei „Java“ parametrus perduoda metodams pagal vertę, jei kintamasis rodo į objekto nuorodą, tikrasis objektas taip pat bus pakeistas.

Jei vis dar nėra visiškai aišku, kaip tai veikia, pažvelkite į žemiau pateiktą paveikslą.

Rafaelis Chinelato Del Nero

Ar primityvūs tipai perduodami pagal vertę?

Kaip ir objektų tipai, primityvūs tipai taip pat perduodami pagal vertę. Ar galite išvardinti, kas nutiks primityviesiems tipams, pateiktame šiame kodo pavyzdyje?

 viešoji klasė „PrimitiveByValueExample“ {public static void main (String ... primitiveByValue) {int homerAge = 30; „changeHomerAge“ („homerAge“); System.out.println (homerAge); } statinis tuštumos pokytisHomerAge (int homerAge) {homerAge = 35; }} 

Jei nustatėte, kad vertė pasikeis į 30, esate teisus. Tai 30, nes (vėl) „Java“ perduoda objekto parametrus pagal vertę. Skaičius 30 yra tik vertės, o ne tikrosios vertės kopija. Pirminiai tipai yra priskirti kamino atmintyje, todėl bus pakeista tik vietinė reikšmė. Šiuo atveju nėra objekto nuorodos.

Nepakeičiamų objektų nuorodų perdavimas

Kas būtų, jei tą patį testą atliktume su nekintamu Stygos objektas?

JDK yra daug nekintamų klasių. Pavyzdžiui, apvyniojimo tipai Sveikasis skaičius, Dvigubai, Plūdė, Ilgas, Būlio, Didelis dešimtainis, ir, žinoma, labai gerai žinoma Stygos klasė.

Kitame pavyzdyje atkreipkite dėmesį, kas nutinka, kai keičiame a reikšmę Stygos.

 public class StringValueChange {public static void main (String ... doYourBest) {String name = ""; „changeToHomer“ (vardas); System.out.println (vardas); } static void changeToHomer (String name) {name = "Homer"; }} 

Kaip manote, kokia bus produkcija? Jei atspėjote „“, tada sveikiname! Taip nutinka todėl, kad a Stygos objektas yra nekintamas, o tai reiškia, kad laukai Stygos yra galutiniai ir jų negalima pakeisti.

Padaryti Stygos klasės nekintama suteikia mums geresnę kontrolę vienam iš dažniausiai naudojamų „Java“ objektų. Jei a reikšmė Stygos galima pakeisti, tai sukeltų daug klaidų. Taip pat atkreipkite dėmesį, kad nekeičiame atributo Stygos klasė; vietoj to mes tiesiog priskiriame naują Stygos vertę. Tokiu atveju „Homero“ vertė bus perduodama vardas viduje konors „changeToHomer“ metodas. Stygos "Homeris" galės būti renkamas šiukšles iš karto „changeToHomer“ metodas užbaigia vykdymą. Nors objekto pakeisti negalima, vietinis kintamasis bus.

Stygos ir dar daugiau

Sužinokite daugiau apie „Java“ Stygos klasė ir dar daugiau: Peržiūrėkite visus Rafaelio įrašus „Java Challengers“ serijoje.

Perduodamos kintamų objektų nuorodos

Skirtingai Stygos, dauguma JDK objektų yra kintantys, pvz., „StringBuilder“ klasė. Žemiau pateiktas pavyzdys yra panašus į ankstesnį, tačiau yra funkcijų „StringBuilder“ geriau nei Stygos:

 static class MutableObjectReference {public static void main (String ... mutableObjectExample) {StringBuilder name = new StringBuilder ("Homer"); addSureName (vardas); System.out.println (vardas); } static void addSureName (StringBuilder vardas) {name.append ("Simpson"); }} 

Ar galite išvesti šio pavyzdžio išvestį? Šiuo atveju, kadangi dirbame su keičiamu objektu, išvestis bus „Homeras Simpsonas“. To paties elgesio galite tikėtis iš bet kurio kito „Java“ kintamo objekto.

Jūs jau sužinojote, kad „Java“ kintamieji perduodami pagal vertę, tai reiškia, kad perduodama vertės kopija. Tiesiog nepamirškite, kad nukopijuota vertė nurodo a tikras objektas „Java“ atminties kaupe. Praėjus vertybei, vis tiek keičiama tikro objekto vertė.

Paimkite objektų nuorodų iššūkį!

Šiame „Java Challenger“ išbandysime tai, ką sužinojote apie objektų nuorodas. Žemiau pateiktame kodo pavyzdyje matote nekintamą Stygos ir kintamas „StringBuilder“ klasė. Kiekvienas iš jų yra perduodamas kaip metodo parametras. Žinant, kad „Java“ praeina tik pagal vertę, kokia, jūsų manymu, bus išvestis, kai bus įvykdytas pagrindinis šios klasės metodas?

 public class DragonWarriorReferenceChallenger {public static void main (String ... doYourBest) {StringBuilder warriorProfession = new StringBuilder ("Dragon"); Styginis warriorWeapon = "Kardas"; changeWarriorClass (warriorProfession, warriorWeapon); System.out.println ("Warrior =" + warriorProfession + "Ginklas =" + warriorWeapon); } static void changeWarriorClass (StringBuilder warriorProfession, String ginklas) {warriorProfession.append ("Knight"); ginklas = "Drakonas" + ginklas; ginklas = nulis; warriorProfession = null; }} 

Čia pateikiamos parinktys, ieškokite atsakymo rakto šio straipsnio pabaigoje.

A: Karys = null Ginklas = null

B: Karys = Drakono ginklas = Drakonas

C: Karys = Drakono riterio ginklas = Drakono kardas

D: Karys = Drakono riterio ginklas = Kardas

Kas tik nutiko?

Pirmasis parametras aukščiau pateiktame pavyzdyje yra karysProfesija kintamasis, kuris yra kintamas objektas. Antrasis parametras - ginklas - yra nekintamas Stygos:

 static void changeWarriorClass (StringBuilder warriorProfession, String ginklas) {...} 

Dabar išanalizuokime, kas vyksta šio metodo viduje. Pirmoje šio metodo eilutėje pridedame Riteris vertė karysProfesija kintamasis. Prisiminti, kad karysProfesija yra kintamas objektas; todėl tikrasis objektas bus pakeistas, o jo vertė bus „Drakono riteris“.

 warriorProfession.append („Riteris“); 

Antroje instrukcijoje nekintamas vietinis Stygos kintamasis bus pakeistas į „Drakono kardas“. Tačiau tikrasis objektas niekada nebus pakeistas Stygos yra nekintamas ir jo atributai yra galutiniai:

 ginklas = "Drakonas" + ginklas; 

Galiausiai mes praeiname niekinis čia esantiems kintamiesiems, bet ne objektams. Objektai išliks tokie patys, kol jie vis dar bus pasiekiami išorėje - šiuo atveju naudojant pagrindinį metodą. Nors vietiniai kintamieji bus nuliniai, objektams nieko nenutiks:

 ginklas = nulis; warriorProfession = null; 

Iš viso to galime daryti išvadą, kad galutinės mūsų kintamos vertės „StringBuilder“ ir nekintamas Stygos bus:

 System.out.println ("Warrior =" + warriorProfession + "Ginklas =" + warriorWeapon); 

Vienintelė vertė, pasikeitusi „changeWarriorClass“ metodas buvo karysProfesija, nes tai yra kintama „StringBuilder“ objektas. Prisimink tai karysGinklas nepasikeitė, nes tai nekintama Stygos objektas.

Teisinga išvestis iš „Challenger“ kodo būtų:

D: Karys = Drakono riterio ginklas = Kardas.

Vaizdo iššūkis! Objekto nuorodų derinimas „Java“

Derinimas yra vienas iš paprasčiausių būdų visiškai įsisavinti programavimo koncepcijas, kartu tobulinant kodą. Šiame vaizdo įraše galite sekti, kol aš derinu ir paaiškinu „Java“ objektų nuorodas.

Dažniausios klaidos su objekto nuorodomis

  • Bandoma pakeisti nekintamą vertę remiantis nuoroda.
  • Bandoma pakeisti primityvų kintamąjį pagal nuorodą.
  • Tikimasi, kad tikrasis objektas nepasikeis, kai metode pakeisite kintamo objekto parametrą.

Ką atsiminti apie objektų nuorodas

  • „Java“ visada perduoda parametrų kintamuosius pagal vertę.
  • „Java“ objektų kintamieji visada nurodo tikrąjį objektą, esantį atminties kaupe.
  • Kintamo objekto vertė gali būti pakeista, kai ji perduodama metodui.
  • Nekintamo objekto vertės negalima pakeisti, net jei jam perduodama nauja reikšmė.
  • „Perduodama pagal vertę“ reiškia vertės kopijos perdavimą.
  • „Perdavimas pagal nuorodą“ reiškia tikrosios kintamojo nuorodos perdavimą atmintyje.

Sužinokite daugiau apie „Java“

  • Gaukite daugiau greitų kodo patarimų: perskaitykite visus Rafaelio įrašus „JavaWorld Java Challengers“ serijoje.
  • Sužinokite daugiau apie kintamus ir nekintamus „Java“ objektus (pvz., Stygos ir „StringBuffer“) ir kaip juos naudoti kode.
  • Galbūt nustebsite sužinoję, kad primityvūs „Java“ tipai yra prieštaringi. Ši funkcija John I. Moore nurodo, kaip juos laikyti ir išmokti gerai jais naudotis.
  • Kurkite savo „Java“ programavimo įgūdžius „Java Dev Gym“.
  • Jei jums patiko derinti „Java“ paveldėjimą, peržiūrėkite daugiau vaizdo įrašų Rafaelio „Java Challenges“ vaizdo įrašų grojaraštyje (šios serijos vaizdo įrašai nėra susiję su „JavaWorld“).
  • Norite dirbti su projektais be streso ir parašyti kodą be klaidų? Eikite į „NoBugsProject“, kur rasite savo kopiją Jokių klaidų, jokio streso - sukurkite gyvenimą keičiančią programinę įrangą, nesunaikindami savo gyvenimo.

Ši istorija: „Ar„ Java “praeina pagal nuorodą, ar perduoda vertę?“ iš pradžių buvo išleista „JavaWorld“.