1. Referensvariabler

I Java-språket finns det två sorters variabler: primitiva variabler och allt annat. Som det händer ska vi prata om "allt annat" nu.

I själva verket skulle det vara mer korrekt att säga att det finns primitiva variabler och referensvariabler . Så vad är dessa referensvariabler?

Till skillnad från primitiva typer, vars variabler lagrar värden direkt, lagrar referensvariabler referenser till objekt. Det vill säga, det finns ett objekt någonstans i minnet, och referensvariabeln lagrar helt enkelt adressen till detta objekt i minnet (en referens till objektet).

Endast primitiva typer lagrar värden direkt i variabler. Alla andra typer lagrar endast en objektreferens . Förresten, du har redan stött på två sådana typer av variabler - Stringvariabler och arrayvariabler .

Både en array och en sträng är objekt lagrade någonstans i minnet. Stringvariabler och arrayvariabler lagrar endast referenser till objekt.

Referensvariabler i Java

int a, int b and double där primitiva variabler som lagrar sina värden inom sig själva.

En String strvariabel är en referens och lagrar adressen (referensen) till ett Stringobjekt i minnet.

När man tilldelar ett primitivt värde till en variabel av en primitiv typ, kopieras (dupliceras) dess värde. När du tilldelar en referensvariabel kopieras endast objektets adresssjälva objektet kopieras inte .


2. Vad handlar referenser om?

Vad är den grundläggande skillnaden mellan referensvariabler och primitiva variabler?

En primitiv variabel är som en ruta: du kan lagra något värde i den. En referensvariabel är mer som ett papper med ett telefonnummer på.

En bil vs nycklar till bilen

Föreställ dig att du bestämmer dig för att ge din vän en bil på hans födelsedag. Du kommer inte att slå in den i en låda och bära den med dig: bilen är för stor för det.

Det är mycket bekvämare att bara presentera bilnycklarna i en låda som är stor nog att innehålla dem. Din vän kommer att förstå allt när han får nycklarna ur lådan. Det finns ingen anledning att bära hela bilen med dig när du bara kan lämna över nycklarna.

En person kontra hennes telefonnummer

Eller här är en annan jämförelse: en person och hennes telefonnummer. Ett telefonnummer är inte personen, men ett telefonnummer kan användas för att ringa henne, be henne om information eller ge instruktioner.

På liknande sätt används en referens för att interagera med ett objekt. Alla objekt interagerar med varandra med hjälp av referenser. Istället för att "byta folk" byter vi helt enkelt telefonnummer.

När man tilldelar ett värde till en primitiv variabel, kopieras (dupliceras) dess värde. När man tilldelar ett värde till en referensvariabel kopieras endast adressen (telefonnumret) till objektet – själva objektet kopieras inte.

En referens erbjuder ytterligare en fördel: du kan skicka en objektreferens till någon metod, och metoden kommer att kunna modifiera (ändra) objektet genom att använda referensen till det, anropa dess metoder och komma åt data inuti objektet.


3. Tilldela referenser

Vid tilldelning av referensvariabler tilldelas endast objektets adress i minnet. Objekten i sig dyker inte upp eller försvinner.

Detta tillvägagångssätt undviker att kopiera stora mängder minne. Om du behöver skicka ett mycket stort objekt till en metod skickar vi bara objektreferensen och det är allt. Referensen tar mycket mindre plats.

Tilldela referenser

Storleken på alla referensvariabler (oavsett typ) är densamma — 4 byte (som en int). Men! Om din applikation körs på en 64-bitars Java-maskin kommer alla referenser att vara 8 byte (64 bitar) stora.

Dessutom kan referenser endast tilldelas varandra. Du kan inte ändra referenser eller tilldela godtyckliga värden till referensvariabler:

Koda Beskrivning
String hello = "Hello";
String s = hello;
Detta är tillåtet
String hello = "Hello";
hello++;
Men detta är inte tillåtet
String hello = 0x1234;
Och detta är inte tillåtet

4. En nullreferens

Och vad lagrar en referensvariabel om inget har tilldelats den ännu?

Den lagrar en nollreferens . nullär ett speciellt Java-nyckelord som betyder frånvaron av en referens (en tom referens). Värdet nullkan tilldelas vilken referensvariabel som helst.

Alla referensvariabler är nullsåvida de inte har fått någon form av referens tilldelad.

Exempel:

Koda Beskrivning
class Person
{
   public static String name;
   public static int age;
}


Variabeln String namehar ett standardvärde: null.
Variabeln int agehar ett standardvärde: 0.

Lokala variabler som inte har tilldelats något värde anses oinitierade för både primitiva och referenstyper.

Om en variabel lagrar en referens till något objekt och du vill rensa variabelns värde, tilldela den bara en nollreferens.

Koda Beskrivning
String s = null;
s = "Hello";
s = null;
sbutiker null.
slagrar en referens till ett strängobjekt
slagrar null.

5. Skicka referenser till metoder

Om en metod har parametrar som är referenstyper skickas värden till metoden på samma sätt som när man arbetar med icke-referensvariabler. Parametern tilldelas helt enkelt värdet för den andra variabeln.

Exempel:

Koda Beskrivning
class Solution
{
   public static void fill(String[] array, String value)
   {
      for (int i = 0; i < array.length; i++)
        array[i] = value;
   }

   public static void main(String[] args)
   {
     String[] data = new String[10];
     fill(data, "Hello");
   }
}


Den fillfyller den godkända arrayen ( array) med det godkända värdet ( value).

När fillmetoden anropas arraytilldelas parametern en referens till dataarrayen. Variabeln valuetilldelas en referens till strängobjektet ("Hello").

Så här ser minnet ut innan metoden anropas fill :

Skicka referenser till metoder

Så här ser minnet ut när fill metoden körs :

Skicka referenser till metoder 2

Variablerna dataoch arrayrefererar till (lagrar referenser till) samma behållare i minnet.

Variabeln valuelagrar en referens till strängobjektet ( "Hello").

Cellerna i arrayen lagrar också bara referenser till objektet "Hello".

Faktum är att inga objekt dupliceras – endast referenser kopieras.



6. Jämförelse med språket C/C ++

I intervjuer tillfrågas ibland Java-programmerare hur data överförs till metoder i Java? Och ibland är frågan om data skickas med referens eller värde?

Den här frågan kommer från C++, men är inte särskilt meningsfull i Java . I Java tilldelas parametrar alltid helt enkelt värdena för argumenten. Så det korrekta svaret skulle vara " efter värde ".

Men var beredd att förklara din ståndpunkt , eftersom du omedelbart kan höra repliken: "primitiva typer passeras av värde, och referenstyper skickas med referens."

Detta ursprung till detta problem härrör från det faktum att många Java-programmerare var C++-programmerare tidigare. I det programmeringsspråket var frågan om hur parametrar överförs till metoder mycket viktig.

I Java är allt entydigt: primitiva typer lagrar värden och referenstyper lagrar också ett värde - en referens. Det är en fråga om en variabel anses vara ett värde .

I C++ kan en variabel lagra både en referens till ett objekt och själva objektet. Detsamma gällde om primitiva typer: en primitiv variabel kunde lagra ett värde eller deklarera variabeln som en referens till en int. Så för att undvika förvirring hänvisar C++-programmerare alltid till objektet till en referens som en referens och själva objektet - som ett värde.

I C++ kan du lätt ha situationen där en variabel innehåller ett objekt, men den andra innehåller en referens till det objektet. Följaktligen var frågan om vad en variabel lagrar - själva objektet eller bara en referens till det - mycket viktig. När ett objekt skickades till en metod kopierades det (om det skickades av värde) och inte kopierades (om det skickades med referens).

I Java existerar inte denna dualitet, så det korrekta svaret är: argument skickas till Java-metoder efter värde . Det är bara det att när vi pratar om referensvariabler är detta värde en referens.