Pass-By-Value als een mechanisme voor het doorgeven van parameters in Java

1. Inleiding

De twee meest voorkomende manieren om argumenten door te geven aan methoden zijn "passeren-aan-waarde" en "passeren-door-referentie". Verschillende programmeertalen gebruiken deze concepten op verschillende manieren. Wat Java betreft, is alles strikt Pass-by-Value.

In deze zelfstudie laten we zien hoe Java argumenten voor verschillende typen doorgeeft.

2. Pass-by-Value versus Pass-by-Reference

Laten we beginnen met enkele van de verschillende mechanismen voor het doorgeven van parameters aan functies:

  • waarde
  • referentie
  • resultaat
  • waarde-resultaat
  • naam

De twee meest voorkomende mechanismen in moderne programmeertalen zijn "Pass-by-Value" en "Pass-by-Reference". Laten we, voordat we verder gaan, deze eerst bespreken:

2.1. Pass-by-Value

Wanneer een parameter pass-by-value is, werken de beller en de aangeroepen methode op twee verschillende variabelen die kopieën van elkaar zijn. Wijzigingen in de ene variabele veranderen de andere niet.

Het betekent dat tijdens het aanroepen van een methode, parameters die aan de aangeroepen methode worden doorgegeven, zijn klonen van originele parameters. Elke wijziging die in de aangeroepen methode wordt aangebracht, heeft geen effect op de oorspronkelijke parameters in de aanroepmethode.

2.2. Pass-by-Reference

Wanneer een parameter pass-by-reference is, werken de beller en de aangeroepen persoon op hetzelfde object.

Het betekent dat wanneer een variabele pass-by-reference is, de unieke identificatie van het object wordt naar de methode gestuurd. Elke wijziging in de instantieleden van de parameter zal ertoe leiden dat die wijziging wordt aangebracht in de oorspronkelijke waarde.

3. Parameter doorgeven in Java

De fundamentele concepten in elke programmeertaal zijn "waarden" en "referenties". In Java, Primitieve variabelen slaan de werkelijke waarden op, terwijl niet-primitieven de referentievariabelen opslaan die verwijzen naar de adressen van de objecten waarnaar ze verwijzen. Zowel waarden als referenties worden opgeslagen in het stapelgeheugen.

Argumenten in Java worden altijd op waarde doorgegeven. Tijdens het aanroepen van een methode wordt een kopie van elk argument, of het nu een waarde of een verwijzing is, in het stapelgeheugen gemaakt, dat vervolgens aan de methode wordt doorgegeven.

In het geval van primitieven, wordt de waarde eenvoudig gekopieerd naar het stapelgeheugen, dat vervolgens wordt doorgegeven aan de aangeroepen methode; in het geval van niet-primitieven, verwijst een verwijzing in het stapelgeheugen naar de feitelijke gegevens die zich in de heap bevinden. Wanneer we een object passeren, wordt de referentie in het stapelgeheugen gekopieerd en wordt de nieuwe referentie doorgegeven aan de methode.

Laten we dit nu in actie zien met behulp van enkele codevoorbeelden.

3.1. Primitieve typen passeren

De Java-programmeertaal heeft acht primitieve gegevenstypen. Primitieve variabelen worden direct in het stapelgeheugen opgeslagen. Telkens wanneer een variabele van het primitieve gegevenstype wordt doorgegeven als een argument, worden de feitelijke parameters gekopieerd naar formele argumenten en deze formele argumenten verzamelen hun eigen ruimte in het stapelgeheugen.

De levensduur van deze formele parameters duurt slechts zolang die methode wordt uitgevoerd, en bij terugkeer worden deze formele argumenten uit de stapel gewist en weggegooid.

Laten we proberen het te begrijpen met behulp van een codevoorbeeld:

openbare klasse PrimitivesUnitTest {@Test openbare leegte whenModifyingPrimitives_thenOriginalValuesNotModified () {int x = 1; int y = 2; // Voor wijziging assertEquals (x, 1); assertEquals (y, 2); wijzigen (x, y); // Na wijziging assertEquals (x, 1); assertEquals (y, 2); } openbare statische ongeldige wijziging (int x1, int y1) {x1 = 5; y1 = 10; }} 

Laten we proberen de beweringen in het bovenstaande programma te begrijpen door te analyseren hoe deze waarden in het geheugen worden opgeslagen:

  1. De variabelen 'X" en "y " in de belangrijkste methode zijn primitieve typen en hun waarden worden direct opgeslagen in het stapelgeheugen
  2. Als we method noemen aanpassen()wordt voor elk van deze variabelen een exacte kopie gemaakt en op een andere locatie in het stapelgeheugen opgeslagen
  3. Elke wijziging aan deze kopieën heeft alleen invloed op hen en laat de oorspronkelijke variabelen ongewijzigd

3.2. Objectreferenties doorgeven

In Java worden alle objecten dynamisch opgeslagen in Heap-ruimte onder de motorkap. Deze objecten worden verwezen vanuit referenties die referentievariabelen worden genoemd.

Een Java-object wordt, in tegenstelling tot Primitives, in twee fasen opgeslagen. De referentievariabelen worden opgeslagen in het stapelgeheugen en het object waarnaar ze verwijzen, wordt opgeslagen in een Heap-geheugen.

Telkens wanneer een object als argument wordt doorgegeven, wordt een exacte kopie van de referentievariabele gemaakt die naar dezelfde locatie van het object in het heapgeheugen verwijst als de oorspronkelijke referentievariabele.

Als gevolg hiervan wordt elke wijziging in hetzelfde object in de methode weerspiegeld in het oorspronkelijke object. Als we echter een nieuw object aan de doorgegeven referentievariabele toewijzen, wordt dit niet weerspiegeld in het oorspronkelijke object.

Laten we proberen dit te begrijpen met behulp van een codevoorbeeld:

openbare klasse NonPrimitivesUnitTest {@Test openbare leegte whenModifyingObjects_thenOriginalObjectChanged () {Foo a = nieuwe Foo (1); Foo b = nieuwe Foo (1); // Voor wijziging assertEquals (a.num, 1); assertEquals (b.num, 1); wijzigen (a, b); // Na wijziging assertEquals (a.num, 2); assertEquals (b.num, 1); } openbare statische ongeldige wijziging (Foo a1, Foo b1) {a1.num ++; b1 = nieuwe Foo (1); b1.num ++; }} class Foo {public int num; openbare Foo (int num) {this.num = num; }}

Laten we de beweringen in het bovenstaande programma analyseren. We zijn objecten gepasseerd een en b in aanpassen() methode met dezelfde waarde 1. In eerste instantie verwijzen deze objectreferenties naar twee verschillende objectlocaties in een heap-ruimte:

Wanneer deze referenties een en b worden doorgegeven in de aanpassen() methode, maakt het spiegelkopieën van die verwijzingen a1 en b1 die naar dezelfde oude objecten verwijzen:

In de aanpassen() methode, wanneer we de referentie wijzigen a1, het verandert het originele object. Echter, ter referentie b1, we hebben een nieuw object toegewezen. Het wijst nu dus naar een nieuw object in het heap-geheugen.

Elke wijziging aangebracht in b1 zal niets weerspiegelen in het originele object:

4. Conclusie

In dit artikel hebben we gekeken hoe het doorgeven van parameters wordt afgehandeld in het geval van primitieven en niet-primitieven.

We hebben geleerd dat het doorgeven van parameters in Java altijd Pass-by-Value is. De context verandert echter afhankelijk van of we te maken hebben met primitieven of objecten:

  1. Voor primitieve typen zijn parameters pass-by-value
  2. Voor objecttypen is de objectverwijzing een pass-by-value

De codefragmenten die in dit artikel worden gebruikt, zijn te vinden op GitHub.