Pass-by-Value mint paraméterátadási mechanizmus a Java-ban

1. Bemutatkozás

A két legelterjedtebb módszer, amellyel az argumentumokat átadják a módszereknek, az „érték-átadás” és a „referencia-átadás”. A különböző programozási nyelvek ezeket a fogalmakat különböző módon használják. Ami a Java-t illeti, minden szigorúan Pass-by-Value.

Ebben az oktatóanyagban bemutatjuk, hogyan adja át a Java az argumentumokat a különféle típusokhoz.

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

Kezdjük a paraméterek funkciókhoz való továbbításának különböző mechanizmusaival:

  • érték
  • referencia
  • eredmény
  • érték-eredmény
  • név

A modern programozási nyelvekben a két leggyakoribb mechanizmus a „Pass-by-Value” és a „Pass-by-Reference”. Mielőtt folytatnánk, először beszéljük meg ezeket:

2.1. Pass-by-Value

Ha egy paraméter pass-by-value, a hívó és a callee módszer két különböző változón működnek, amelyek egymás másolatai. Az egyik változó bármilyen módosítása nem módosítja a másikat.

Ez azt jelenti, hogy a módszer meghívása közben A callee módszerhez továbbított paraméterek az eredeti paraméterek klónjai lesznek. A callee módszerrel végzett bármilyen módosítás nem befolyásolja a hívó módszer eredeti paramétereit.

2.2. Pass-by-Reference

Ha egy paraméter passzív referencia, a hívó és a hívott személy ugyanazon az objektumon működik.

Ez azt jelenti, hogy amikor egy változó pass-by-referencia, az objektum egyedi azonosítóját elküldik a metódusnak. A paraméter példánytagjainak bármilyen változása azt eredményezi, hogy az eredeti érték megváltozik.

3. Paraméter átadás Java-ban

Bármely programozási nyelvben az alapfogalmak az „értékek” és a „referenciák”. Java-ban A primitív változók a tényleges értékeket tárolják, míg a nem primitívek a referencia változókat, amelyek az általuk hivatkozott objektumok címére mutatnak. Mind az értékeket, mind a referenciákat a verem memóriájában tároljuk.

A Java-ban szereplő érvek mindig átadhatók. A metódus meghívása során minden argumentum másolata, legyen az érték vagy hivatkozás, létrejön a verem memóriájában, amelyet aztán átad a metódusnak.

Primitívek esetén az értéket egyszerűen átmásolják a verem memóriájába, majd ezt továbbítják a callee módszerre; nem primitívek esetén a verem memóriájában található hivatkozás a halomban található tényleges adatokra mutat. Amikor elhaladunk egy objektumon, a verem memóriájában található hivatkozás átmásolódik, és az új referencia átkerül a módszerhez.

Lássuk ezt most működés közben néhány kódpélda segítségével.

3.1. Primitív típusok átadása

A Java programozási nyelv nyolc primitív adattípust tartalmaz. A primitív változókat közvetlenül a verem memóriájában tároljuk. Amikor egy primitív adattípus bármely változóját argumentumként adjuk át, a tényleges paraméterek átmásolódnak a formális argumentumokba, és ezek a formális argumentumok felhalmozzák saját területüket a verem memóriájában.

Ezeknek a formális paramétereknek az élettartama csak addig tart, amíg ez a módszer fut, és visszatérésük után ezeket a formális argumentumokat kitörlik a veremből, és elvetik.

Próbáljuk megérteni egy kódpélda segítségével:

public class PrimitivesUnitTest {@Test public void whenModifyingPrimitives_thenOriginalValuesNotModified () {int x = 1; int y = 2; // A módosítás előtt assertEquals (x, 1); assertEquals (y, 2); módosítani (x, y); // Módosítás után assertEquals (x, 1); assertEquals (y, 2); } public static void modify (int x1, int y1) {x1 = 5; y1 = 10; }} 

Próbáljuk megérteni a fenti program állításait azáltal, hogy elemezzük, hogyan tárolják ezeket az értékeket a memóriában:

  1. A „x" és „y ” a fő módszerben primitív típusok vannak, és értékeik közvetlenül a verem memóriájában tárolódnak
  2. Amikor metódust hívunk módosít(), ezeknek a változóknak a pontos másolata jön létre, és a verem memóriájában egy másik helyen tárolódik
  3. Ezen másolatok bármilyen módosítása csak őket érinti, és az eredeti változókat változatlanul hagyja

3.2. Objektum hivatkozások átadása

A Java-ban az összes objektum dinamikusan a Heap térben van a motorháztető alatt. Ezeket az objektumokat referenciaváltozóknak nevezett hivatkozásokból hivatkozjuk.

A Java objektumokat a Primitivekkel ellentétben két szakaszban tárolják. A referenciaváltozók a verem memóriájában vannak tárolva, az általuk hivatkozott objektumok pedig egy kupac memóriában vannak tárolva.

Amikor egy objektumot argumentumként adunk át, a referencia változó pontos másolata jön létre, amely az objektumnak a halom memóriájában található helyére mutat, mint az eredeti referencia változó.

Ennek eredményeként, valahányszor változtatunk ugyanabban az objektumban a módszerben, ez a változás az eredeti objektumban is megjelenik. Ha azonban az átadott referencia változóhoz új objektumot rendelünk, akkor az nem fog tükröződni az eredeti objektumban.

Próbáljuk megérteni ezt egy kódpélda segítségével:

public class NonPrimitivesUnitTest {@Test public void whenModifyingObjects_thenOriginalObjectChanged () {Foo a = new Foo (1); Foo b = új Foo (1); // A módosítás előtt assertEquals (a.num, 1); assertEquals (b.num, 1); módosítani (a, b); // Módosítás után assertEquals (a.num, 2); assertEquals (b.num, 1); } public static void modify (Foo a1, Foo b1) {a1.num ++; b1 = új Foo (1); b1.num ++; }} osztály Foo {public int num; public Foo (int szám) {this.num = num; }}

Elemezzük a fenti program állításait. Tárgyak mellett haladtunk el a és b ban ben módosít() módszer, amelynek értéke azonos 1. Kezdetben ezek az objektum-hivatkozások két különálló objektum-helyre mutatnak egy kupac térben:

Amikor ezek a hivatkozások a és b átadják a módosít() módszerrel tükör másolatokat készít ezekről a hivatkozásokról a1 és b1 amelyek ugyanazokra a régi tárgyakra mutatnak:

Ban,-ben módosít() módszer, amikor módosítjuk a referenciát a1, megváltoztatja az eredeti objektumot. Viszont referenciaként b1, új objektumot rendeltünk hozzá. Tehát most egy új objektumra mutat a kupac memóriában.

Bármilyen változás történt b1 nem tükröz semmit az eredeti objektumban:

4. Következtetés

Ebben a cikkben azt vizsgáltuk, hogyan kezelik a paraméterek átadását primitívek és nem primitívek esetén.

Megtudtuk, hogy a Java-ban a paraméter-átadás mindig Pass-by-Value. A kontextus azonban attól függően változik, hogy primitívekkel vagy objektumokkal van-e dolgunk:

  1. A primitív típusoknál a paraméterek átengedési értékek
  2. Objektumtípusok esetén az objektum hivatkozás átadási érték

Az ebben a cikkben használt kódrészletek a GitHubon találhatók.