Pass-By-Value som en Parameter Passing Mechanism i Java

1. Introduktion

De to mest udbredte måder at videregive argumenter til metoder er "forbipasserende værdi" og "forbipasserende reference". Forskellige programmeringssprog bruger disse begreber på forskellige måder. For Java er alt strengt Pass-by-værdi.

I denne vejledning skal vi illustrere, hvordan Java sender argumenter til forskellige typer.

2. Pass-by-værdi vs Pass-by-Reference

Lad os starte med nogle af de forskellige mekanismer til overføring af parametre til funktioner:

  • værdi
  • reference
  • resultat
  • værdi-resultat
  • navn

De to mest almindelige mekanismer i moderne programmeringssprog er "Pass-by-Value" og "Pass-by-Reference". Lad os først diskutere disse, inden vi fortsætter:

2.1. Pass-by-værdi

Når en parameter er forbipasserende, fungerer den, der ringer op og callee-metoden på to forskellige variabler, der er kopier af hinanden. Enhver ændring af den ene variabel ændrer ikke den anden.

Det betyder, at mens man kalder en metode, parametre, der sendes til callee-metoden, vil være kloner af originale parametre. Enhver ændring foretaget i callee-metoden har ingen indflydelse på de oprindelige parametre i opkaldsmetoden.

2.2. Pass-by-Reference

Når en parameter er forbipasserende, fungerer opkalderen og callee på det samme objekt.

Det betyder, at når en variabel er forbipasserende, objektets unikke identifikator sendes til metoden. Enhver ændring af parameterens instansmedlemmer resulterer i, at ændringen foretages til den oprindelige værdi.

3. Parameter-overføring i Java

De grundlæggende begreber i ethvert programmeringssprog er "værdier" og "referencer". I Java, Primitive variabler gemmer de faktiske værdier, mens ikke-primitiver gemmer referencevariablerne, der peger på adresserne på de objekter, de henviser til. Både værdier og referencer er gemt i stakhukommelsen.

Argumenter i Java overføres altid til værdi. Under metodeopkald oprettes en kopi af hvert argument, hvad enten det er en værdi eller reference, i stakhukommelsen, som derefter sendes til metoden.

I tilfælde af primitiver kopieres værdien simpelthen inde i stack-hukommelsen, som derefter sendes til callee-metoden; i tilfælde af ikke-primitiver peger en henvisning i stakhukommelsen til de faktiske data, der findes i bunken. Når vi passerer et objekt, kopieres referencen i stack-hukommelsen, og den nye reference sendes til metoden.

Lad os nu se dette i aktion ved hjælp af nogle kodeeksempler.

3.1. Passerer primitive typer

Java Programming Language har otte primitive datatyper. Primitive variabler gemmes direkte i stack-hukommelsen. Hver gang en variabel af primitiv datatype sendes som et argument, kopieres de faktiske parametre til formelle argumenter, og disse formelle argumenter akkumulerer deres eget rum i stakhukommelsen.

Levetiden for disse formelle parametre varer kun, så længe denne metode kører, og når de vender tilbage, ryddes disse formelle argumenter væk fra stakken og kasseres.

Lad os prøve at forstå det ved hjælp af et kodeeksempel:

public class PrimitivesUnitTest {@Test public void whenModifyingPrimitives_thenOriginalValuesNotModified () {int x = 1; int y = 2; // Før ændring hævderEquals (x, 1); assertEquals (y, 2); ændre (x, y); // Efter modifikation assertEquals (x, 1); assertEquals (y, 2); } offentlig statisk tomrumsmodifikation (int x1, int y1) {x1 = 5; y1 = 10; }} 

Lad os prøve at forstå påstandene i ovenstående program ved at analysere, hvordan disse værdier er gemt i hukommelsen:

  1. Variablerne “x" og “y ” i hovedmetoden er primitive typer, og deres værdier er direkte gemt i stakhukommelsen
  2. Når vi kalder metode modificere(), oprettes en nøjagtig kopi for hver af disse variabler og lagres på et andet sted i stakhukommelsen
  3. Enhver ændring af disse kopier påvirker kun dem og efterlader de originale variabler uændrede

3.2. Refererende objekt

I Java gemmes alle objekter dynamisk i dyngerummet under emhætten. Disse objekter henvises fra referencer kaldet referencevariabler.

Et Java-objekt lagres i modsætning til Primitives i to faser. Referencevariablerne er gemt i stackhukommelsen, og det objekt, som de henviser til, er gemt i en Heap-hukommelse.

Hver gang et objekt sendes som et argument, oprettes en nøjagtig kopi af referencevariablen, der peger på den samme placering af objektet i bunkehukommelsen som den oprindelige referencevariabel.

Som et resultat af dette, når vi foretager ændringer i det samme objekt i metoden, reflekteres denne ændring i det originale objekt. Men hvis vi tildeler et nyt objekt til den beståede referencevariabel, afspejles den ikke i det oprindelige objekt.

Lad os prøve at forstå dette ved hjælp af et kodeeksempel:

public class NonPrimitivesUnitTest {@Test public void whenModifyingObjects_thenOriginalObjectChanged () {Foo a = new Foo (1); Foo b = ny Foo (1); // Før modifikation assertEquals (a.num, 1); assertEquals (b.num, 1); ændre (a, b); // Efter modifikation assertEquals (a.num, 2); assertEquals (b.num, 1); } offentlig statisk tomrumsmodifikation (Foo a1, Foo b1) {a1.num ++; b1 = ny Foo (1); b1.num ++; }} klasse Foo {public int num; offentlig Foo (int num) {this.num = num; }}

Lad os analysere påstandene i ovenstående program. Vi har passeret genstande -en og b i modificere() metode, der har samme værdi 1. Oprindeligt peger disse objekthenvisninger på to forskellige objektplaceringer i et bunkerum:

Når disse referencer -en og b passeres i modificere() metode skaber den spejlkopier af disse referencer a1 og b1 der peger på de samme gamle objekter:

I modificere() metode, når vi ændrer reference a1, det ændrer det originale objekt. Dog for en reference b1, vi har tildelt et nyt objekt. Så det peger nu på et nyt objekt i bunkehukommelse.

Enhver ændring foretaget i b1 afspejler ikke noget i det originale objekt:

4. Konklusion

I denne artikel så vi på, hvordan parameteroverføring håndteres i tilfælde af primitiver og ikke-primitiver.

Vi lærte, at parameteroverføring i Java altid er Pass-by-Value. Men konteksten ændres afhængigt af om vi har at gøre med primitiver eller objekter:

  1. For primitive typer er parametre forbipasseringsværdi
  2. For objekttyper er objektreferencen forbipasserende værdi

Kodestykker, der bruges i denne artikel, kan findes på GitHub.