1. Referansevariabler
I Java-språket er det to typer variabler: primitive variabler og alt annet. Som det skjer, skal vi snakke om "alt annet" nå.
Faktisk ville det være mer riktig å si at det er primitive variabler og referansevariabler . Så hva er disse referansevariablene?
I motsetning til primitive typer, hvis variabler lagrer verdier direkte, lagrer referansevariabler referanser til objekter. Det vil si at det er et objekt et sted i minnet, og referansevariabelen lagrer ganske enkelt adressen til dette objektet i minnet (en referanse til objektet).
Bare primitive typer lagrer verdier direkte i variabler. Alle andre typer lagrer kun en objektreferanse . Forresten, du har allerede møtt to slike typer variabler - String
variabler og matrisevariabler .
Både en matrise og en streng er objekter lagret et sted i minnet. String
variabler og matrisevariabler lagrer kun referanser til objekter.
int a, int b and double d
er primitive variabler som lagrer verdiene deres inne i seg selv.
En String str
variabel er en referanse og lagrer adressen (referansen) til et String
objekt i minnet.
Når du tilordner en primitiv verdi til en variabel av en primitiv type, blir verdien kopiert (duplisert). Når du tilordner en referansevariabel, blir bare adressen til objektet kopiert – selve objektet kopieres ikke .
2. Hva handler referanser om?
Hva er den grunnleggende forskjellen mellom referansevariabler og primitive variabler?
En primitiv variabel er som en boks: du kan lagre en verdi i den. En referansevariabel er mer som et stykke papir med et telefonnummer på.
En bil vs nøkler til bilen
Tenk deg at du bestemmer deg for å gi vennen din en bil til bursdagen hans. Du vil ikke pakke den inn i en boks og bære den med deg: bilen er for stor til det.
Det er mye mer praktisk å presentere bare bilnøklene i en boks som er stor nok til å inneholde dem. Din venn vil forstå alt når han får nøklene ut av esken. Det er ikke nødvendig å bære hele bilen med deg når du bare kan levere nøklene.
En person vs hennes telefonnummer
Eller her er en annen sammenligning: en person og telefonnummeret hennes. Et telefonnummer er ikke personen, men et telefonnummer kan brukes til å ringe henne, be henne om informasjon eller gi instruksjoner.
På samme måte brukes en referanse for å samhandle med et objekt. Alle objekter samhandler med hverandre ved hjelp av referanser. I stedet for å «bytte folk» utveksler vi rett og slett telefonnumre.
Når du tilordner en verdi til en primitiv variabel, blir verdien kopiert (duplisert). Når du tilordner en verdi til en referansevariabel, blir bare adressen (telefonnummeret) til objektet kopiert - selve objektet kopieres ikke.
En referanse gir enda en fordel: du kan sende en objektreferanse til en eller annen metode, og metoden vil kunne endre (endre) objektet ved å bruke referansen til det, kalle dets metoder og få tilgang til data inne i objektet.
3. Tildeling av referanser
Ved tilordning av referansevariabler tildeles kun objektets adresse i minnet. Gjenstander i seg selv dukker ikke opp eller forsvinner.
Denne tilnærmingen unngår å kopiere store mengder minne. Hvis du trenger å sende et veldig stort objekt til en metode, sender vi bare objektreferansen og det er det. Referansen tar mye mindre plass.
Størrelsen på alle referansevariabler (uavhengig av type) er den samme - 4 byte (som en int). Men! Hvis applikasjonen din kjører på en 64-bits Java-maskin, vil alle referanser være 8 byte (64 biter) i størrelse.
Dessuten kan referanser bare tildeles hverandre. Du kan ikke endre referanser eller tilordne vilkårlige verdier til referansevariabler:
Kode | Beskrivelse |
---|---|
|
Dette er tillatt |
|
Men dette er ikke tillatt |
|
Og dette er ikke tillatt |
4. En null
referanse
Og hva lagrer en referansevariabel hvis ingenting er tilordnet den ennå?
Den lagrer en nullreferanse . null
er et spesielt Java nøkkelord som betyr fravær av en referanse (en tom referanse). Verdien null
kan tilordnes en hvilken som helst referansevariabel.
Alle referansevariabler er null
med mindre de har fått en slags referanse tildelt dem.
Eksempler:
Kode | Beskrivelse |
---|---|
|
Variabelen String name har en standardverdi: null . Variabelen int age har en standardverdi: 0 . |
Lokale variabler som ikke har blitt tildelt en verdi, anses som uinitialisert for både primitive og referansetyper.
Hvis en variabel lagrer en referanse til et objekt, og du vil slette variabelens verdi, tilordner du den bare en nullreferanse.
Kode | Beskrivelse |
---|---|
|
s butikker null . s lagrer en referanse til et strengobjekt s lagrer null . |
5. Sende referanser til metoder
Hvis en metode har parametere som er referansetyper , overføres verdier til metoden på samme måte som når man arbeider med ikke-referansevariabler. Parameteren blir ganske enkelt tildelt verdien til den andre variabelen.
Eksempel:
Kode | Beskrivelse |
---|---|
|
Den fill fyller den beståtte matrisen ( array ) med den beståtte verdien ( value ). |
Når fill
metoden kalles, array
tilordnes parameteren en referanse til data
matrisen. Variabelen value
er tilordnet en referanse til strengobjektet ("Hei").
Slik ser minnet ut før du kaller fill
metoden:
Slik ser minnet ut når fill
metoden kjører :

Variablene data
og array
refererer til (lagre referanser til) den samme beholderen i minnet.
Variabelen value
lagrer en referanse til strengobjektet ( "Hello"
).
Cellene i matrisen lagrer også bare referanser til objektet "Hello"
.
Faktisk er ingen objekter duplisert - bare referanser kopieres.
6. Sammenligning med C/C ++-språket
I intervjuer blir noen ganger Java-programmerere spurt om hvordan data overføres til metoder i Java? Og noen ganger er spørsmålet om data sendes med referanse eller verdi?
Dette spørsmålet kommer fra C++, men er lite meningsfullt i Java . I Java tildeles parametere alltid bare verdiene til argumentene. Så det riktige svaret ville være " etter verdi ".
Men vær forberedt på å forklare posisjonen din , siden du umiddelbart kan høre replikken: "primitive typer overføres av verdi, og referansetyper sendes ved referanse."
Denne opprinnelsen til dette problemet stammer fra det faktum at mange Java-programmerere var C++-programmerere tidligere. I det programmeringsspråket var spørsmålet om hvordan parametere overføres til metoder veldig viktig.
I Java er alt entydig: primitive typer lagrer verdier og referansetyper lagrer også en verdi - en referanse. Det er et spørsmål om en variabel anses som en verdi .
I C++ kan en variabel lagre både en referanse til et objekt og selve objektet. Det samme gjaldt om primitive typer: en primitiv variabel kunne lagre en verdi eller erklære variabelen som en referanse til en int
. Så, for å unngå forvirring, refererer C++-programmerere alltid til objektet til en referanse som en referanse , og selve objektet - som en verdi.
I C++ kan du lett ha situasjonen der en variabel inneholder et objekt, men den andre inneholder en referanse til det objektet. Følgelig var spørsmålet om hva en variabel lagrer - selve objektet eller bare en referanse til det - veldig viktig. Når et objekt ble sendt til en metode, ble det kopiert (hvis sendt med verdi), og ikke kopiert (hvis sendt ved referanse).
I Java eksisterer ikke denne dualiteten, så det riktige svaret er: argumenter sendes til Java-metoder etter verdi . Det er bare det at når vi snakker om referansevariabler, er denne verdien en referanse.
GO TO FULL VERSION