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 - Stringvariabler og matrisevariabler .

Både en matrise og en streng er objekter lagret et sted i minnet. Stringvariabler og matrisevariabler lagrer kun referanser til objekter.

Referansevariabler i Java

int a, int b and double der primitive variabler som lagrer verdiene deres inne i seg selv.

En String strvariabel er en referanse og lagrer adressen (referansen) til et Stringobjekt 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 kopiertselve 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.

Tildeling av referanser

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
String hello = "Hello";
String s = hello;
Dette er tillatt
String hello = "Hello";
hello++;
Men dette er ikke tillatt
String hello = 0x1234;
Og dette er ikke tillatt

4. En nullreferanse

Og hva lagrer en referansevariabel hvis ingenting er tilordnet den ennå?

Den lagrer en nullreferanse . nuller et spesielt Java nøkkelord som betyr fravær av en referanse (en tom referanse). Verdien nullkan tilordnes en hvilken som helst referansevariabel.

Alle referansevariabler er nullmed mindre de har fått en slags referanse tildelt dem.

Eksempler:

Kode Beskrivelse
class Person
{
   public static String name;
   public static int age;
}


Variabelen String namehar en standardverdi: null.
Variabelen int agehar 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
String s = null;
s = "Hello";
s = null;
sbutikker null.
slagrer en referanse til et strengobjekt
slagrer 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
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 beståtte matrisen ( array) med den beståtte verdien ( value).

Når fillmetoden kalles, arraytilordnes parameteren en referanse til datamatrisen. Variabelen valueer tilordnet en referanse til strengobjektet ("Hei").

Slik ser minnet ut før du kaller fill metoden:

Sende referanser til metoder

Slik ser minnet ut når fill metoden kjører :

Sende referanser til metoder 2

Variablene dataog arrayrefererer til (lagre referanser til) den samme beholderen i minnet.

Variabelen valuelagrer 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.