Programovanie

Prejde Java odkazom alebo prejde hodnotou?

Mnoho programovacích jazykov umožňuje odovzdávanie parametrov referenciou alebo hodnotou. V Jave môžeme odovzdávať iba parametre podľa hodnoty. To ukladá určité obmedzenia a tiež vyvoláva otázky. Napríklad ak sa v metóde zmení hodnota parametra, čo sa stane s hodnotou nasledujúcou po vykonaní metódy? Tiež by vás mohlo zaujímať, ako Java spravuje hodnoty objektov v halde pamäte. Toto Java Challenger pomáha vám vyriešiť tieto a ďalšie bežné otázky týkajúce sa referencií na objekty v prostredí Java.

Získajte zdrojový kód

Získajte kód pre tento Java Challenger. Podľa príkladov môžete spustiť svoje vlastné testy.

Odkazy na objekty sú odovzdávané podľa hodnoty

Všetky odkazy na objekty v Jave sú odovzdávané podľa hodnoty. To znamená, že kópia hodnoty bude odovzdaná metóde. Trik však spočíva v tom, že odovzdaním kópie hodnoty sa zmení aj skutočná hodnota objektu. Aby ste pochopili prečo, začnite týmto príkladom:

 public class 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"; }} trieda Simpson {názov reťazca; } 

Čo si myslíš simpson.name bude po transformIntoHomer metóda je vykonaná?

V tomto prípade to bude Homer! Dôvod je ten, že premenné objektov Java sú jednoducho referencie, ktoré ukazujú na skutočné objekty v halde pamäte. Preto aj keď Java odovzdáva parametre metódam podľa hodnoty, ak premenná ukazuje na odkaz na objekt, zmení sa aj skutočný objekt.

Ak stále nemáte celkom jasno v tom, ako to funguje, pozrite sa na obrázok nižšie.

Rafael Chinelato Del Nero

Prechádzajú primitívne typy podľa hodnoty?

Rovnako ako typy objektov, aj primitívne typy sa odovzdávajú podľa hodnoty. Môžete odvodiť, čo sa stane s primitívnymi typmi v nasledujúcom príklade kódu?

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

Ak ste zistili, že hodnota sa zmení na 30, máte pravdu. Je to 30, pretože (opäť) Java odovzdáva parametre objektu podľa hodnoty. Číslo 30 je iba kópiou hodnoty, nie skutočnej hodnoty. Primitívne typy sú alokované v pamäti zásobníka, takže sa zmení iba lokálna hodnota. V tomto prípade neexistuje odkaz na objekt.

Odovzdávanie nemenných odkazov na objekty

Čo keby sme urobili ten istý test s nemenným String objekt?

JDK obsahuje veľa nemenných tried. Príklady zahŕňajú typy obalov Celé číslo, Dvojitý, Plavák, Dlhé, Boolovský, BigDecimal, a samozrejme veľmi dobre známy String trieda.

V nasledujúcom príklade si všimnite, čo sa stane, keď zmeníme hodnotu a String.

 public class StringValueChange {public static void main (String ... doYourBest) {Názov reťazca = ""; changeToHomer (meno); System.out.println (názov); } static void changeToHomer (názov reťazca) {name = "Homer"; }} 

Čo si myslíte, aký bude výstup? Ak ste uhádli „“, gratulujeme! Stáva sa to preto, lebo a String objekt je nemenný, čo znamená, že polia vo vnútri String sú konečné a nemožno ich zmeniť.

Výroba String trieda nemenná nám dáva lepšiu kontrolu nad jedným z najpoužívanejších objektov Java. Ak je hodnota a String by sa dalo zmeniť, vytvorilo by to veľa chýb. Upozorňujeme tiež, že nemeníme atribút String trieda; namiesto toho jednoducho priradíme nový String hodnotu. V takom prípade bude hodnota „Homer“ odovzdaná názov v changeToHomer metóda. The String „Homer“ bude oprávnený na zber odpadu hneď po changeToHomer metóda dokončí vykonanie. Aj keď objekt nemožno zmeniť, miestna premenná bude.

Struny a ďalšie

Získajte viac informácií o prostredí Java String trieda a viac: Pozrite si všetky príspevky od Rafaela v sérii Java Challengers.

Prebieha odovzdávanie premenlivých odkazov na objekty

Na rozdiel od String, väčšina objektov v JDK je premenlivá, ako napríklad StringBuilder trieda. Nižšie uvedený príklad je podobný predchádzajúcemu, ale obsahuje funkcie StringBuilder radšej než String:

 statická trieda MutableObjectReference {public static void main (String ... mutableObjectExample) {StringBuilder name = new StringBuilder ("Homer"); addSureName (meno); System.out.println (názov); } static void addSureName (StringBuilder name) {name.append ("Simpson"); }} 

Môžete odvodiť výstup pre tento príklad? V tomto prípade, pretože pracujeme s premenlivým objektom, bude výstupom „Homer Simpson“. Rovnaké správanie by ste mohli očakávať od iného premenlivého objektu v Jave.

Už ste sa dozvedeli, že premenné jazyka Java sa odovzdávajú podľa hodnoty, čo znamená, že sa odovzdáva kópia hodnoty. Pamätajte, že kopírovaná hodnota ukazuje na a skutočný objekt v halde pamäte Java. Prechádzanie okolo hodnoty stále mení hodnotu skutočného objektu.

Zúčastnite sa výzvy na referencie na objekty!

V tomto Java Challenger otestujeme, čo ste sa dozvedeli o referenciách na objekty. V príklade kódu nižšie vidíte nemenné String a premenlivý StringBuilder trieda. Každá sa odovzdáva ako parameter metóde. Ak si uvedomíte, že jazyk Java prechádza iba podľa hodnoty, aký bude podľa vás výstup po vykonaní hlavnej metódy z tejto triedy?

 public class 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, strunová zbraň) {warriorProfession.append ("Knight"); zbraň = "drak" + zbraň; zbraň = null; warriorProfession = null; }} 

Tu sú uvedené možnosti, na konci tohto článku nájdete kľúč odpovede.

A: Bojovník = null Zbraň = null

B: Warrior = Dragon Weapon = Dragon

C.: Warrior = Dragon Knight Weapon = Dragon Sword

D: Warrior = Dragon Knight Weapon = Sword

Čo sa to práve stalo?

Prvý parameter vo vyššie uvedenom príklade je bojovníkProfesia premenná, čo je premenlivý objekt. Druhý parameter, zbraň, je nemenný String:

 static void changeWarriorClass (StringBuilder warriorProfession, strunová zbraň) {...} 

Teraz si poďme analyzovať, čo sa deje v rámci tejto metódy. V prvom riadku tejto metódy pripojíme znak Rytier hodnota do bojovníkProfesia premenná. Zapamätaj si to bojovníkProfesia je premenlivý objekt; skutočný objekt sa preto zmení a hodnota z neho bude „Dragon Knight“.

 warriorProfession.append ("Rytier"); 

V druhej inštrukcii nemenný miestny String premenná sa zmení na „Dragon Sword“. Skutočný objekt sa však nikdy nezmení String je nemenný a jeho atribúty sú konečné:

 zbraň = "drak" + zbraň; 

Nakoniec minieme nulový k premenným tu, ale nie k objektom. Predmety zostanú rovnaké, pokiaľ budú naďalej prístupné externe - v tomto prípade hlavným spôsobom. A hoci budú lokálne premenné nulové, objektom sa nič nestane:

 zbraň = null; warriorProfession = null; 

Z toho všetkého môžeme vyvodiť záver, že konečné hodnoty z našej premennej StringBuilder a nemenný String bude:

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

Jediná hodnota, ktorá sa zmenila v changeWarriorClass metóda bola bojovníkProfesia, pretože je to premenlivé StringBuilder objekt. Poznač si to bojovníkZbraň sa nezmenilo, pretože je to nemenné String objekt.

Správny výstup z nášho kódu Challenger by bol:

D: Warrior = Dragon Knight Weapon = Sword.

Video výzva! Ladenie referencií na objekty v Jave

Ladenie je jedným z najjednoduchších spôsobov, ako úplne absorbovať programovacie koncepty a zároveň vylepšiť váš kód. V tomto videu môžete sledovať, kým ladím a vysvetľujem odkazy na objekty v Jave.

Bežné chyby s odkazmi na objekty

  • Pokúšam sa zmeniť nemennú hodnotu odkazom.
  • Pokus o zmenu primitívnej premennej pomocou odkazu.
  • Očakávanie skutočného objektu sa nezmení, keď v metóde zmeníte parameter premenlivého objektu.

Čo si pamätať o referenciách na objekty

  • Java vždy odovzdáva premenné parametrov podľa hodnoty.
  • Objektové premenné v Jave vždy ukazujú na skutočný objekt v halde pamäte.
  • Hodnotu premenlivého objektu je možné zmeniť, keď sa odovzdá metóde.
  • Hodnotu nemenného objektu nie je možné zmeniť, ani keď sa mu odovzdá nová hodnota.
  • Výraz „odovzdávanie podľa hodnoty“ označuje odovzdanie kópie hodnoty.
  • „Passing by reference“ označuje odovzdanie skutočného odkazu na premennú v pamäti.

Získajte viac informácií o prostredí Java

  • Získajte viac rýchlych tipov na kód: Prečítajte si všetky príspevky od Rafaela v sérii JavaWorld Java Challengers.
  • Získajte viac informácií o premenlivých a nemenných objektoch Java (napríklad String a StringBuffer) a spôsob ich použitia v kóde.
  • Možno vás prekvapí, že primitívne typy Java sú kontroverzné. V tejto funkcii je John I. Moore zástancom ich uchovania a naučenia sa ich dobre používať.
  • Pokračujte v budovaní svojich programovacích schopností v Jave v Java Dev Gym.
  • Ak sa vám páčilo ladenie dedičstva Java, pozrite si ďalšie videá v zozname videí Rafael's Java Challenges (videá v tejto sérii nie sú spojené s JavaWorld).
  • Chcete pracovať na projektoch bez stresu a písať bezchybný kód? Zamierte do NoBugsProject pre svoju kópiu Žiadne chyby, žiadny stres - vytvorte softvér, ktorý vám zmení život, bez toho, aby vám zničil život.

Tento príbeh: „Prejde Java odkazom alebo prekoná hodnotu?“ pôvodne vyšla vo vydavateľstve JavaWorld.

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