1. Referencevariabler

I Java-sproget er der to slags variable: primitive variable og alt muligt andet. Som det sker, kommer vi til at tale om "alt andet" nu.

Faktisk ville det være mere korrekt at sige, at der er primitive variable og referencevariable . Så hvad er disse referencevariabler?

I modsætning til primitive typer, hvis variabler gemmer værdier direkte, gemmer referencevariable referencer til objekter. Det vil sige, at der er et objekt et sted i hukommelsen, og referencevariablen gemmer simpelthen adressen på dette objekt i hukommelsen (en reference til objektet).

Kun primitive typer gemmer værdier direkte inde i variabler. Alle andre typer gemmer kun en objektreference . Forresten har du allerede stødt på to sådanne typer variabler - Stringvariabler og matrixvariabler .

Både et array og en streng er objekter gemt et eller andet sted i hukommelsen. Stringvariabler og matrixvariabler gemmer kun referencer til objekter.

Referencevariabler i Java

int a, int b and double der primitive variable, der gemmer deres værdier i sig selv.

En String strvariabel er en reference og gemmer adressen (referencen) til et Stringobjekt i hukommelsen.

Når du tildeler en primitiv værdi til en variabel af en primitiv type, kopieres dens værdi (duplikeres). Når du tildeler en referencevariabel, kopieres kun objektets adresse - selve objektet kopieres ikke .


2. Hvad handler referencer om?

Hvad er den grundlæggende forskel mellem referencevariabler og primitive variabler?

En primitiv variabel er som en boks: du kan gemme en vis værdi i den. En referencevariabel er mere som et stykke papir med et telefonnummer på.

En bil vs nøgler til bilen

Forestil dig, at du beslutter dig for at give din ven en bil til hans fødselsdag. Du vil ikke pakke den ind i en æske og bære den med dig: det er bilen for stor til.

Det er meget mere praktisk kun at præsentere bilnøglerne i en kasse, der er stor nok til at indeholde dem. Din ven vil forstå alt, når han får nøglerne ud af kassen. Der er ingen grund til at have hele bilen med, når du blot kan aflevere nøglerne.

En person vs hendes telefonnummer

Eller her er en anden sammenligning: en person og hendes telefonnummer. Et telefonnummer er ikke personen, men et telefonnummer kan bruges til at ringe til hende, bede hende om nogle oplysninger eller give instruktioner.

På samme måde bruges en reference til at interagere med et objekt. Alle objekter interagerer med hinanden ved hjælp af referencer. I stedet for at "udveksle folk" udveksler vi blot telefonnumre.

Når du tildeler en værdi til en primitiv variabel, kopieres dens værdi (duplikeres). Når der tildeles en værdi til en referencevariabel, kopieres kun objektets adresse (telefonnummer) - selve objektet kopieres ikke.

En reference giver endnu en fordel: du kan videregive en objektreference til en eller anden metode, og metoden vil være i stand til at ændre (ændre) objektet ved at bruge referencen til det, kalde dets metoder og få adgang til data inde i objektet.


3. Tildeling af referencer

Ved tildeling af referencevariable tildeles kun objektets adresse i hukommelsen. Objekter i sig selv dukker ikke op eller forsvinder.

Denne fremgangsmåde undgår at kopiere store mængder hukommelse. Hvis du skal sende et meget stort objekt til en metode, sender vi bare objektreferencen, og det er det. Referencen fylder meget mindre.

Tildeling af referencer

Størrelsen af ​​alle referencevariabler (uanset deres type) er den samme - 4 bytes (som en int). Men! Hvis din applikation kører på en 64-bit Java-maskine, vil alle referencer være 8 bytes (64 bits) store.

Desuden kan referencer kun tildeles hinanden. Du kan ikke ændre referencer eller tildele vilkårlige værdier til referencevariabler:

Kode Beskrivelse
String hello = "Hello";
String s = hello;
Dette er tilladt
String hello = "Hello";
hello++;
Men dette er ikke tilladt
String hello = 0x1234;
Og dette er ikke tilladt

4. En nullreference

Og hvad gemmer en referencevariabel, hvis der ikke er tildelt noget endnu?

Den gemmer en nul- reference. nuller et specielt Java nøgleord, der betyder fraværet af en reference (en tom reference). Værdien nullkan tildeles enhver referencevariabel.

Alle referencevariabler er, nullmedmindre de har fået tildelt en form for reference.

Eksempler:

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


Variablen String namehar en standardværdi: null.
Variablen int agehar en standardværdi: 0.

Lokale variable, der ikke er blevet tildelt en værdi, betragtes som uinitialiserede for både primitive og referencetyper.

Hvis en variabel gemmer en reference til et eller andet objekt, og du vil rydde variablens værdi, skal du blot tildele den en nul-reference.

Kode Beskrivelse
String s = null;
s = "Hello";
s = null;
sbutikker null.
sgemmer en reference til et strengobjekt
sgemmer null.

5. Videregivelse af referencer til metoder

Hvis en metode har parametre, der er referencetyper , overføres værdier til metoden på samme måde, som når man arbejder med ikke-referencevariabler. Parameteren tildeles simpelthen værdien af ​​den anden variabel.

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 filludfylder den beståede matrix ( array) med den beståede værdi ( value).

Når fillmetoden kaldes, arraytildeles parameteren en reference til dataarrayet. Variablen valuetildeles en reference til strengobjektet ("Hej").

Sådan ser hukommelsen ud, før du kalder fill metoden:

Videregivelse af referencer til metoder

Sådan ser hukommelsen ud, når fill metoden kører :

Videregivelse af referencer til metoder 2

Variablerne dataog arrayrefererer til (lagre referencer til) den samme beholder i hukommelsen.

Variablen valuegemmer en reference til strengobjektet ( "Hello").

Cellerne i arrayet gemmer også blot referencer til objektet "Hello".

Faktisk er ingen objekter duplikeret - kun referencer kopieres.



6. Sammenligning med C/C++ sproget

I interviews bliver Java-programmører nogle gange spurgt, hvordan data overføres til metoder i Java? Og nogle gange er spørgsmålet, om data videregives ved reference eller ved værdi?

Dette spørgsmål kommer fra C++, men er ikke særlig meningsfuldt i Java . I Java tildeles parametre altid blot værdierne af argumenterne. Så det rigtige svar ville være " efter værdi ".

Men vær forberedt på at forklare din holdning , da du måske straks hører replikken: "primitive typer videregives af værdi, og referencetyper videregives ved reference."

Denne oprindelse til dette problem stammer fra det faktum, at mange Java-programmører var C++-programmører i fortiden. I det programmeringssprog var spørgsmålet om, hvordan parametre overføres til metoder, meget vigtigt.

I Java er alt utvetydigt: primitive typer gemmer værdier og referencetyper gemmer også en værdi - en reference. Det er et spørgsmål om, hvorvidt en variabel betragtes som en værdi .

I C++ kan en variabel lagre både en reference til et objekt og selve objektet. Det samme gjaldt om primitive typer: en primitiv variabel kunne lagre en værdi eller erklære variablen som en reference til en int. Så for at undgå forvirring henviser C++-programmører altid til objektet til en reference som en reference og selve objektet - som en værdi.

I C++ kunne du nemt have den situation, hvor den ene variabel indeholder et objekt, men den anden indeholder en reference til det pågældende objekt. Derfor var spørgsmålet om, hvad en variabel lagrer - selve objektet eller blot en reference til det - meget vigtigt. Når et objekt blev videregivet til en metode, blev det kopieret (hvis videregivet af værdi), og ikke kopieret (hvis videregivet ved reference).

I Java eksisterer denne dualitet ikke, så det korrekte svar er: argumenter sendes til Java-metoder efter værdi . Det er bare, at når vi taler om referencevariable, er denne værdi en reference.