Programování

Projde Java odkazem nebo předá hodnotu?

Mnoho programovacích jazyků umožňuje předávání parametrů podle odkazu nebo podle hodnoty. V Javě můžeme předávat pouze parametry podle hodnoty. To ukládá určitá omezení a také vyvolává otázky. Například pokud se v metodě změní hodnota parametru, co se stane s hodnotou následující po provedení metody? Také vás může zajímat, jak Java spravuje hodnoty objektů v haldě paměti. Tento Java Challenger vám pomůže vyřešit tyto a další běžné otázky týkající se odkazů na objekty v Javě.

Získejte zdrojový kód

Získejte kód pro tento Java Challenger. Při provádění příkladů můžete spustit vlastní testy.

Odkazy na objekty jsou předávány podle hodnoty

Všechny odkazy na objekty v Javě jsou předávány podle hodnoty. To znamená, že kopie hodnoty bude předána metodě. Trik však spočívá v tom, že předáním kopie hodnoty se také změní skutečná hodnota objektu. Abyste pochopili proč, začněte tímto příkladem:

 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"; }} třída Simpson {název řetězce; } 

Co si myslíš simpson.name bude po transformovat do Homeru metoda je provedena?

V tomto případě to bude Homer! Důvodem je to, že proměnné objektů Java jsou jednoduše odkazy, které ukazují na skutečné objekty v haldě paměti. Proto i když Java předává parametry metodám podle hodnoty, pokud proměnná ukazuje na odkaz na objekt, změní se také skutečný objekt.

Pokud si stále nejste zcela jisti, jak to funguje, podívejte se na obrázek níže.

Rafael Chinelato Del Nero

Jsou primitivní typy předávány hodnotou?

Stejně jako typy objektů jsou primitivní typy předávány také podle hodnoty. Můžete odvodit, co se stane s primitivními typy v následujícím příkladu 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; }} 

Pokud jste zjistili, že by se hodnota změnila na 30, máte pravdu. Je to 30, protože (opět) Java předává parametry objektu podle hodnoty. Číslo 30 je pouze kopií hodnoty, nikoli skutečné hodnoty. Primitivní typy jsou přidělovány v paměti zásobníku, takže se změní pouze lokální hodnota. V tomto případě neexistuje žádný odkaz na objekt.

Předávání neměnných odkazů na objekty

Co kdybychom provedli stejný test s neměnným Tětiva objekt?

JDK obsahuje mnoho neměnných tříd. Mezi příklady patří typy obalů Celé číslo, Dvojnásobek, Plovák, Dlouho, Booleovský, BigDecimala samozřejmě velmi dobře známé Tětiva třída.

V dalším příkladu si všimněte, co se stane, když změníme hodnotu a Tětiva.

 public class StringValueChange {public static void main (String ... doYourBest) {název řetězce = ""; changeToHomer (název); System.out.println (název); } static void changeToHomer (název řetězce) {name = "Homer"; }} 

Jaký bude podle vás výstup? Pokud jste uhodli „“, pak vám gratulujeme! To se stává, protože a Tětiva objekt je neměnný, což znamená, že pole uvnitř Tětiva jsou konečné a nelze je změnit.

Vytváření Tětiva třída neměnná nám dává lepší kontrolu nad jedním z nejpoužívanějších objektů Java. Pokud je hodnota a Tětiva mohl by být změněn, vytvořilo by to spoustu chyb. Upozorňujeme, že neměníme atribut Tětiva třída; místo toho jednoduše přiřadíme nový Tětiva hodnotu. V takovém případě bude hodnota „Homer“ předána název v changeToHomer metoda. The Tětiva „Homer“ bude způsobilý ke sběru odpadků, jakmile changeToHomer metoda dokončí provedení. Přestože objekt nelze změnit, místní proměnná bude.

Struny a další

Další informace o prostředí Java Tětiva třída a další: Podívejte se na všechny příspěvky Rafaela v sérii Java Challengers.

Předávání proměnlivých odkazů na objekty

Na rozdíl od Tětiva, většina objektů v JDK je proměnlivá, jako StringBuilder třída. Níže uvedený příklad je podobný předchozímu, ale obsahuje funkce StringBuilder spíše než Tětiva:

 statická třída MutableObjectReference {public static void main (String ... mutableObjectExample) {StringBuilder name = new StringBuilder ("Homer"); addSureName (jméno); System.out.println (název); } static void addSureName (StringBuilder name) {name.append ("Simpson"); }} 

Můžete odvodit výstup pro tento příklad? V tomto případě, protože pracujeme s proměnlivým objektem, bude výstup „Homer Simpson“. Stejné chování můžete očekávat od jakéhokoli jiného proměnlivého objektu v Javě.

Už jste se dozvěděli, že proměnné Java jsou předávány podle hodnoty, což znamená, že je předána kopie hodnoty. Nezapomeňte, že kopírovaná hodnota ukazuje na a skutečný objekt v haldě paměti Java. Předávání hodnoty stále mění hodnotu skutečného objektu.

Přijměte výzvu k odkazům na objekty!

V tomto Java Challengeru otestujeme, co jste se dozvěděli o referencích na objekty. V níže uvedeném příkladu kódu vidíte neměnné Tětiva a proměnlivý StringBuilder třída. Každý je předáván jako parametr metodě. Věříte, že Java předává pouze podle hodnoty, co si myslíte, že bude výstupem po provedení hlavní metody z této třídy?

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

Zde jsou možnosti, na konci tohoto článku najdete klíč odpovědi.

A: Warrior = null Zbraň = null

B: Warrior = Dragon Weapon = Dragon

C: Warrior = Dragon Knight Weapon = Dragon Sword

D: Warrior = Dragon Knight Weapon = Sword

Co se právě stalo?

První parametr ve výše uvedeném příkladu je válečníkProfese proměnná, což je proměnlivý objekt. Druhý parametr, zbraň, je neměnný Tětiva:

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

Nyní analyzujme, co se děje uvnitř této metody. Na první řádek této metody připojíme Rytíř hodnota do válečníkProfese proměnná. Pamatuj si to válečníkProfese je proměnlivý objekt; skutečný objekt bude proto změněn a hodnota z něj bude „Dragon Knight“.

 warriorProfession.append ("Rytíř"); 

Ve druhém pokynu je neměnný místní Tětiva proměnná bude změněna na „Dračí meč“. Skutečný objekt se však od té doby nikdy nezmění Tětiva je neměnný a jeho atributy jsou konečné:

 zbraň = "drak" + zbraň; 

Nakonec projdeme nula k proměnným zde, ale ne k objektům. Objekty zůstanou stejné, pokud jsou stále přístupné externě - v tomto případě prostřednictvím hlavní metody. A i když budou lokální proměnné nulové, objektům se nic nestane:

 zbraň = null; warriorProfession = null; 

Ze všeho toho můžeme usoudit, že konečné hodnoty z našeho proměnného StringBuilder a neměnný Tětiva bude:

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

Jediná hodnota, která se změnila v changeWarriorClass metoda byla válečníkProfese, protože je to proměnlivé StringBuilder objekt. Všimněte si, že válečníkZbraň se nezměnilo, protože je to neměnné Tětiva objekt.

Správný výstup z našeho kódu Challenger by byl:

D: Warrior = Dragon Knight Weapon = Sword.

Video výzva! Ladění odkazů na objekty v Javě

Ladění je jedním z nejjednodušších způsobů, jak plně absorbovat programovací koncepty a zároveň vylepšit váš kód. V tomto videu můžete sledovat, zatímco ladím a vysvětluji odkazy na objekty v Javě.

Časté chyby s odkazy na objekty

  • Pokus o změnu neměnné hodnoty odkazem.
  • Pokus o změnu primitivní proměnné odkazem.
  • Očekávání skutečného objektu se nezmění, když v metodě změníte parametr proměnlivého objektu.

Co si pamatovat o odkazech na objekty

  • Java vždy předává proměnné parametrů podle hodnoty.
  • Proměnné objektů v Javě vždy ukazují na skutečný objekt v haldě paměti.
  • Hodnotu proměnlivého objektu lze změnit, když je předána metodě.
  • Hodnotu neměnného objektu nelze změnit, i když je předána nová hodnota.
  • „Předávání podle hodnoty“ označuje předávání kopie hodnoty.
  • „Předávání odkazem“ označuje předávání skutečné reference proměnné v paměti.

Další informace o prostředí Java

  • Získejte více rychlých tipů na kód: Přečtěte si všechny příspěvky Rafaela v sérii JavaWorld Java Challengers.
  • Další informace o proměnlivých a neměnných objektech Java (například Tětiva a StringBuffer) a jak je použít v kódu.
  • Možná vás překvapí, že primitivní typy Javy jsou kontroverzní. V této funkci je John I. Moore důvodem k tomu, aby je udržel a naučil se je dobře používat.
  • Pokračujte v budování svých programovacích dovedností Java v prostředí Java Dev Gym.
  • Pokud se vám líbilo ladění dědičnosti Java, podívejte se na další videa v seznamu videí Rafael's Java Challenges (videa v této sérii nejsou přidružena k JavaWorld).
  • Chcete pracovat na projektech bez stresu a psát bezchybný kód? Vydejte se do NoBugsProject pro svou kopii Žádné chyby, žádný stres - vytvořte software, který změní život, aniž by vám zničil život.

Tento příběh: „Projde Java odkazem nebo předá hodnotu?“ byl původně publikován společností JavaWorld.

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