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 - String
variabler och arrayvariabler .
Både en array och en sträng är objekt lagrade någonstans i minnet. String
variabler och arrayvariabler lagrar endast referenser till objekt.
int a, int b and double d
är primitiva variabler som lagrar sina värden inom sig själva.
En String str
variabel är en referens och lagrar adressen (referensen) till ett String
objekt 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 adress – sjä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.
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 |
---|---|
|
Detta är tillåtet |
|
Men detta är inte tillåtet |
|
Och detta är inte tillåtet |
4. En null
referens
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 null
kan tilldelas vilken referensvariabel som helst.
Alla referensvariabler är null
såvida de inte har fått någon form av referens tilldelad.
Exempel:
Koda | Beskrivning |
---|---|
|
Variabeln String name har ett standardvärde: null . Variabeln int age har 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 |
---|---|
|
s butiker null . s lagrar en referens till ett strängobjekt s lagrar 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 |
---|---|
|
Den fill fyller den godkända arrayen ( array ) med det godkända värdet ( value ). |
När fill
metoden anropas array
tilldelas parametern en referens till data
arrayen. Variabeln value
tilldelas en referens till strängobjektet ("Hello").
Så här ser minnet ut innan metoden anropas fill
:
Så här ser minnet ut när fill
metoden körs :

Variablerna data
och array
refererar till (lagrar referenser till) samma behållare i minnet.
Variabeln value
lagrar 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.
GO TO FULL VERSION