Programiranje

Ali Java prenaša referenco ali vrednost?

Številni programski jeziki omogočajo posredovanje parametrov po referenci ali vrednosti. V Javi lahko posredujemo samo parametre po vrednosti. To postavlja nekatere omejitve in sproža tudi vprašanja. Če se na primer vrednost vrednosti parametra spremeni v metodi, kaj se zgodi z vrednostjo po izvedbi metode? Lahko se tudi vprašate, kako Java upravlja vrednosti predmetov v kopici pomnilnika. To Java Challenger vam pomaga razrešiti ta in druga pogosta vprašanja o referencah objektov v Javi.

Pridobite izvorno kodo

Pridobite kodo za ta Java Challenger. Med sledenjem primerom lahko izvajate lastne teste.

Sklici na objekte se posredujejo po vrednosti

Vse reference na objekt v Javi se posredujejo po vrednosti. To pomeni, da bo kopija vrednosti posredovana metodi. Trik pa je v tem, da posredovanje kopije vrednosti spremeni tudi dejansko vrednost predmeta. Da bi razumeli, zakaj, začnite s tem primerom:

 javni razred ObjectReferenceExample {public static void main (String ... doYourBest) {Simpson simpson = new Simpson (); transformIntoHomer (simpson); System.out.println (simpson.name); } static void transformIntoHomer (Simpson simpson) {simpson.name = "Homer"; }} razred Simpson {Ime niza; } 

Kaj misliš simpson.name bo po transformIntoHomer metoda se izvaja?

V tem primeru bo Homer! Razlog je v tem, da so Java objektne spremenljivke preprosto sklici, ki kažejo na resnične predmete v kopici pomnilnika. Torej, čeprav Java posreduje parametre metodam po vrednosti, če spremenljivka kaže na sklic na objekt, bo spremenjen tudi resnični objekt.

Če še vedno niste povsem jasni, kako to deluje, si oglejte spodnjo sliko.

Rafael Chinelato Del Nero

Ali se primitivni tipi posredujejo po vrednosti?

Tako kot tipi predmetov se tudi primitivni tipi posredujejo po vrednosti. Ali lahko v naslednjem primeru kode ugotovite, kaj se bo zgodilo s primitivnimi tipi?

 javni razred PrimitiveByValueExample {public static void main (String ... primitiveByValue) {int homerAge = 30; changeHomerAge (homerAge); System.out.println (homerAge); } static void changeHomerAge (int homerAge) {homerAge = 35; }} 

Če ste ugotovili, da se bo vrednost spremenila na 30, imate prav. Ura je 30, ker (spet) Java posreduje parametre objekta po vrednosti. Število 30 je le kopija vrednosti, ne pa resnična vrednost. Primitivni tipi so dodeljeni v pomnilniku sklada, zato bo spremenjena le lokalna vrednost. V tem primeru referenca na objekt ni.

Posredovanje nespremenljivih referenc na objekt

Kaj če bi isti test naredili z nespremenljivo Vrvica predmet?

JDK vsebuje veliko nespremenljivih razredov. Primeri vključujejo vrste ovoja Celo število, Dvojno, Float, dolga, Logično, BigDecimal, in seveda zelo dobro znano Vrvica razred.

V naslednjem primeru opazite, kaj se zgodi, ko spremenimo vrednost a Vrvica.

 javni razred StringValueChange {public static void main (String ... doYourBest) {String name = ""; changeToHomer (ime); System.out.println (ime); } static void changeToHomer (ime niza) {name = "Homer"; }} 

Kakšen bo po vašem mnenju rezultat? Če ste uganili “”, potem čestitam! To se zgodi, ker a Vrvica je nespremenljiv, kar pomeni, da so polja znotraj Vrvica so dokončni in jih ni mogoče spremeniti.

Izdelava Vrvica class nespremenljiv nam daje boljši nadzor nad enim najpogosteje uporabljanih Javinih predmetov. Če je vrednost a Vrvica lahko spremenili, ustvarili bi veliko napak. Upoštevajte tudi, da ne spreminjamo lastnosti atributa Vrvica razred; namesto tega preprosto dodelimo novo Vrvica vrednost zanj. V tem primeru bo vrednost »Homer« posredovana ime v changeToHomer metoda. The Vrvica "Homer" bo upravičen do odvoza smeti takoj, ko bo changeToHomer metoda zaključi izvedbo. Čeprav predmeta ni mogoče spremeniti, bo lokalna spremenljivka.

Strune in še več

Preberite več o Javi Vrvica razred in še več: Oglejte si vse Rafaelove objave v seriji Java Challengers.

Prenos referenc spremenljivih predmetov

Za razliko Vrvica, večina predmetov v JDK je spremenljivih, kot je StringBuilder razred. Spodnji primer je podoben prejšnjemu, vendar ima funkcije StringBuilder raje kot Vrvica:

 statični razred MutableObjectReference {javna statična void glavna (String ... mutableObjectExample) {StringBuilder name = new StringBuilder ("Homer"); addSureName (ime); System.out.println (ime); } statična praznina addSureName (ime StringBuilder) {name.append ("Simpson"); }} 

Ali lahko za ta primer ugotovite rezultat? Ker v tem primeru delamo s spremenljivim predmetom, bo rezultat »Homer Simpson«. Pričakovali bi lahko enako vedenje od katerega koli drugega spremenljivega predmeta v Javi.

Že ste se naučili, da se Java spremenljivke posredujejo po vrednosti, kar pomeni, da se posreduje kopija vrednosti. Ne pozabite, da kopirana vrednost kaže na a pravi predmet v kopici pomnilnika Java. Podajanje mimo vrednosti še vedno spremeni vrednost resničnega predmeta.

Sprejmite izziv referenc predmetov!

V tem Java Challengerju bomo preizkusili, kaj ste se naučili o referencah objektov. V spodnjem primeru kode vidite nespremenljivo Vrvica in spremenljiv StringBuilder razred. Vsak se posreduje kot parameter metodi. Če veste, da Java prehaja samo po vrednosti, kaj mislite, da bo rezultat, ko bo izvedena glavna metoda iz tega razreda?

 javni razred DragonWarriorReferenceChallenger {public static void main (String ... doYourBest) {StringBuilder warriorProfession = new StringBuilder ("Dragon"); String warriorWeapon = "Meč"; changeWarriorClass (warriorProfession, warriorWeapon); System.out.println ("Warrior =" + warriorProfession + "Weapon =" + warriorWeapon); } static void changeWarriorClass (StringBuilder warriorProfession, String orožje) {warriorProfession.append ("Knight"); orožje = "zmaj" + orožje; orožje = nič; warriorProfession = null; }} 

Tu so možnosti, ključ za odgovor poiščite na koncu tega članka.

A: Warrior = null Orožje = null

B: Warrior = Zmajevo orožje = Zmaj

C: Warrior = Dragon Knight Weapon = Zmajev meč

D: Warrior = Dragon Knight Weapon = Meč

Kaj se je pravkar zgodilo?

Prvi parameter v zgornjem primeru je warriorProfession spremenljivka, ki je spremenljiv objekt. Drugi parameter, orožje, je nespremenljiv Vrvica:

 static void changeWarriorClass (StringBuilder warriorProfession, String orožje) {...} 

Zdaj pa analizirajmo, kaj se dogaja znotraj te metode. V prvi vrstici te metode dodamo Vitez vrednost za warriorProfession spremenljivka. Zapomni si to warriorProfession je spremenljiv predmet; zato se bo stvarni predmet spremenil in njegova vrednost bo "Dragon Knight."

 warriorProfession.append ("Vitez"); 

V drugem navodilu nespremenljivi lokalni Vrvica spremenljivka bo spremenjena v "Dragon Sword." Resnični predmet pa se ne bo nikoli več spremenil Vrvica je nespremenljiv in njegovi atributi so dokončni:

 orožje = "zmaj" + orožje; 

Končno gremo mimo nič na spremenljivke tukaj, ne pa tudi na predmete. Predmeti bodo ostali enaki, dokler bodo še vedno dostopni od zunaj - v tem primeru prek glavne metode. In čeprav bodo lokalne spremenljivke nične, se s predmeti ne bo zgodilo nič:

 orožje = nič; warriorProfession = null; 

Iz vsega tega lahko sklepamo, da so končne vrednosti iz naše spremenljive StringBuilder in nespremenljiv Vrvica bo:

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

Edina vrednost, ki se je spremenila v changeWarriorClass metoda je bila warriorProfession, ker je spremenljiv StringBuilder predmet. Upoštevajte to bojevnikOrožje ni spremenilo, ker je nespremenljivo Vrvica predmet.

Pravilni izhod iz naše kode Challenger bi bil:

D: Warrior = Dragon Knight Weapon = Meč.

Video izziv! Odpravljanje napak na reference predmeta v Javi

Odpravljanje napak je eden najlažjih načinov za popolno absorpcijo konceptov programiranja, hkrati pa izboljšate kodo. V tem videoposnetku lahko sledite, medtem ko odpravljam napake in razlagam sklice na predmete v Javi.

Pogoste napake pri sklicih na objekte

  • Poskus spremeniti nespremenljivo vrednost s sklicem.
  • Poskus spremeniti primitivno spremenljivko s sklicem.
  • Pričakovanje pravega predmeta se ne bo spremenilo, ko v metodi spremenite spremenljiv parameter objekta.

Kaj si je treba zapomniti pri referencah predmetov

  • Java vedno posreduje spremenljivke parametrov po vrednosti.
  • Predmetne spremenljivke v Javi vedno kažejo na pravi predmet v kopici pomnilnika.
  • Vrednost spremenljivega predmeta je mogoče spremeniti, ko je posredovana metodi.
  • Vrednosti nespremenljivega predmeta ni mogoče spremeniti, tudi če mu je posredovana nova vrednost.
  • »Prenos vrednosti« se nanaša na posredovanje kopije vrednosti.
  • "Prenos referenc" se nanaša na posredovanje dejanske reference spremenljivke v pomnilnik.

Preberite več o Javi

  • Pridobite več hitrih nasvetov za kodo: preberite vse objave Rafaela v seriji JavaWorld Java Challengers.
  • Preberite več o spremenljivih in nespremenljivih predmetih Java (kot je Vrvica in StringBuffer) in kako jih uporabiti v kodi.
  • Morda boste presenečeni, ko boste izvedeli, da so primitivni tipi Jave sporni. V tej funkciji John I. Moore utemeljuje njihovo ohranjanje in učenje, da jih dobro uporablja.
  • Svoje veščine programiranja Java nadaljujte v telovadnici Java Dev.
  • Če vam je bilo všeč razhroščevanje dedovanja Java, si oglejte več videoposnetkov na seznamu predvajanja videoposnetkov Rafael's Java Challenges (videoposnetki v tej seriji niso povezani z JavaWorldom).
  • Bi radi delali na projektih brez stresa in pisali kodo brez napak? Pojdite na NoBugsProject za vaš izvod Brez napak, brez stresa - ustvarite programsko opremo, ki spreminja življenje, ne da bi uničili svoje življenje.

Ta zgodba "Ali Java prehaja mimo reference ali mimo vrednosti?" je prvotno objavil JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found