Pass-By-Value ako mechanizmus odovzdávania parametrov v Jave

1. Úvod

Dva najrozšírenejšie spôsoby odovzdávania argumentov metódam sú „odovzdávanie podľa hodnoty“ a „odovzdávanie podľa referencií“. Rôzne programovacie jazyky používajú tieto koncepty rôznymi spôsobmi. Čo sa týka Javy, všetko je prísne Pass-by-Value.

V tomto výučbe si ukážeme, ako Java odovzdáva argumenty pre rôzne typy.

2. Pass-by-Value vs Pass-by-Reference

Začnime s niektorými z rôznych mechanizmov na prenos parametrov do funkcií:

  • hodnotu
  • odkaz
  • výsledok
  • hodnota-vysledok
  • názov

Dva najbežnejšie mechanizmy v moderných programovacích jazykoch sú „Pass-by-Value“ a „Pass-by-Reference“. Predtým, ako pokračujeme, si najskôr pohovoríme:

2.1. Pass-by-Value

Keď je parameter parametrom pass-by-value, volajúci a metóda volaného pracujú na dvoch rôznych premenných, ktoré sú navzájom kópiami. Žiadne zmeny jednej premennej druhú nezmenia.

Znamená to, že pri volaní metódy parametre odovzdané volanej metóde budú klony pôvodných parametrov. Akákoľvek úprava vykonaná metódou volaného nebude mať žiadny vplyv na pôvodné parametre metódy volajúceho.

2.2. Pass-by-Reference

Keď je parametrom parameter pass-by-reference, volajúci a volaný operujú na rovnakom objekte.

To znamená, že keď je premenná pass-by-reference, metóde sa odosiela jedinečný identifikátor objektu. Akékoľvek zmeny členov inštancie parametra budú mať za následok vykonanie zmeny pôvodnej hodnoty.

3. Predávanie parametrov v Jave

Základné koncepty v akomkoľvek programovacom jazyku sú „hodnoty“ a „referencie“. V Jave Primitívne premenné ukladajú skutočné hodnoty, zatiaľ čo iné ako primitívne uchovávajú referenčné premenné, ktoré odkazujú na adresy objektov, na ktoré odkazujú. Hodnoty aj referencie sú uložené v pamäti zásobníka.

Argumenty v Jave sa odovzdávajú vždy podľa hodnoty. Počas vyvolania metódy sa v pamäti zásobníka vytvorí kópia každého argumentu, či už je to hodnota alebo referencia, ktorá sa potom odovzdá metóde.

V prípade primitívov sa hodnota jednoducho skopíruje do pamäte zásobníka, ktorá sa potom odovzdá volanej metóde; v prípade neprimitívov odkaz na pamäť v zásobníku odkazuje na skutočné údaje, ktoré sa nachádzajú v halde. Keď prechádzame objektom, referencia v pamäti zásobníka sa skopíruje a nový odkaz sa odovzdá metóde.

Pozrime sa teraz na to pomocou niekoľkých príkladov kódu.

3.1. Prechádzajú primitívne typy

Programovací jazyk Java obsahuje osem primitívnych dátových typov. Primitívne premenné sú priamo uložené v zásobníku. Kedykoľvek sa ako argument odovzdá ľubovoľná premenná primitívneho údajového typu, skutočné parametre sa skopírujú do formálnych argumentov a tieto formálne argumenty akumulujú svoj vlastný priestor v pamäti zásobníka.

Životnosť týchto formálnych parametrov trvá iba dovtedy, kým je táto metóda spustená, a po návrate sú tieto formálne argumenty odstránené zo zásobníka a zahodené.

Pokúsme sa to pochopiť pomocou príkladu kódu:

public class PrimitivesUnitTest {@Test public void whenModifyingPrimitives_thenOriginalValuesNotModified () {int x = 1; int y = 2; // Pred úpravou assertEquals (x, 1); assertEquals (y, 2); upraviť (x, y); // Po úprave assertEquals (x, 1); assertEquals (y, 2); } public static void modify (int x1, int y1) {x1 = 5; y1 = 10; }} 

Pokúsme sa pochopiť tvrdenia vo vyššie uvedenom programe analyzovaním toho, ako sú tieto hodnoty uložené v pamäti:

  1. Premenné „X" a „y ” v hlavnej metóde sú primitívne typy a ich hodnoty sú priamo uložené v pamäti zásobníka
  2. Keď voláme metódu upraviť (), pre každú z týchto premenných sa vytvorí presná kópia a uloží sa na inom mieste v pamäti zásobníka
  3. Akákoľvek úprava týchto kópií ovplyvňuje iba ich a ponecháva pôvodné premenné nezmenené

3.2. Odovzdávanie referencií na objekty

V Jave sú všetky objekty dynamicky uložené v halde pod kapotou. Tieto objekty sú odkazované z referencií nazývaných referenčné premenné.

Objekt Java je na rozdiel od Primitive uložený v dvoch fázach. Referenčné premenné sú uložené v pamäti zásobníka a objekt, na ktorý odkazujú, sú uložené v pamäti haldy.

Kedykoľvek sa objekt predá ako argument, vytvorí sa presná kópia referenčnej premennej, ktorá ukazuje na rovnaké umiestnenie objektu v halde pamäte ako pôvodná referenčná premenná.

Výsledkom je, že kedykoľvek vykonáme v metóde akúkoľvek zmenu v rovnakom objekte, táto zmena sa prejaví v pôvodnom objekte. Ak však priradíme nový objekt k odovzdanej referenčnej premennej, nebude sa to prejavovať v pôvodnom objekte.

Pokúsme sa to pochopiť pomocou príkladu kódu:

public class NonPrimitivesUnitTest {@Test public void whenModifyingObjects_thenOriginalObjectChanged () {Foo a = new Foo (1); Foo b = nový Foo (1); // Pred úpravou assertEquals (a.num, 1); assertEquals (b.num, 1); upraviť (a, b); // Po úprave assertEquals (a.num, 2); assertEquals (b.num, 1); } public static void modify (Foo a1, Foo b1) {a1.num ++; b1 = nový Foo (1); b1.num ++; }} trieda Foo {public int num; public Foo (int num) {this.num = num; }}

Poďme si analyzovať tvrdenia vo vyššie uvedenom programe. Minuli sme predmety a a b v upraviť () metóda, ktorá má rovnakú hodnotu 1. Tieto odkazy na objekty spočiatku smerujú na dve odlišné umiestnenia objektov v halde:

Keď tieto odkazy a a b sa odovzdávajú v upraviť () metódou, vytvára zrkadlové kópie týchto referencií a1 a b1 ktoré ukazujú na rovnaké staré objekty:

V upraviť () metóda, keď upravujeme referenciu a1, zmení pôvodný objekt. Avšak pre referenciu b1, priradili sme nový objekt. Takže teraz ukazuje na nový objekt v halde pamäte.

Akákoľvek zmena vykonaná v b1 nebude odrážať nič v pôvodnom objekte:

4. Záver

V tomto článku sme sa pozreli na to, ako sa postupuje s odovzdávaním parametrov v prípade primitívnych a neprimitívnych prvkov.

Dozvedeli sme sa, že odovzdávanie parametrov v Jave je vždy Pass-by-Value. Kontext sa však mení v závislosti od toho, či máme do činenia s primitívmi alebo objektmi:

  1. Pre primitívne typy sú parametre hodnotou pass-by-value
  2. Pre typy objektov je odkazom na objekt údajová hodnota

Útržky kódu použité v tomto článku nájdete na GitHub.


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