1. Referenciaváltozók
A Java nyelvben kétféle változó létezik: primitív változók és minden más. Ahogy megtörténik, most "minden másról" fogunk beszélni.
Valójában helyesebb lenne azt mondani, hogy vannak primitív változók és referenciaváltozók . Tehát mik ezek a referenciaváltozók?
A primitív típusokkal ellentétben, amelyek változói közvetlenül tárolják az értékeket, a referenciaváltozók az objektumokra való hivatkozásokat tárolják. Vagyis van egy objektum valahol a memóriában, és a referenciaváltozó egyszerűen eltárolja ennek az objektumnak a címét a memóriában (hivatkozás az objektumra).
Csak a primitív típusok tárolnak értékeket közvetlenül a változókon belül. Minden más típus csak egy objektumhivatkozást tárol . Mellesleg, már találkozott két ilyen típusú változóval – String
változókkal és tömbváltozókkal .
A tömb és a karakterlánc is valahol a memóriában tárolt objektumok. String
a változók és a tömbváltozók csak az objektumokra való hivatkozásokat tárolják.
int a, int b and double d
primitív változók, amelyek értékeiket magukban tárolják.
A String str
változó egy hivatkozás, és a String
memóriában tárolja egy objektum címét (hivatkozását).
Amikor egy primitív típusú változóhoz primitív értéket adunk, annak értéke másolódik (duplikálódik). Referenciaváltozó hozzárendelésekor csak az objektum címe kerül másolásra – maga az objektum nem kerül másolásra .
2. Miről szólnak a referenciák?
Mi az alapvető különbség a referenciaváltozók és a primitív változók között?
A primitív változó olyan, mint egy doboz: tárolhatunk benne valamilyen értéket. A referenciaváltozó inkább egy papírdarab, amelyen telefonszám található.
Egy autó kontra kulcs az autóhoz
Képzeld el, hogy úgy döntesz, hogy a barátodnak autót adsz születésnapjára. Nem fogod dobozba csomagolni és magaddal vinni: az autó túl nagy ahhoz.
Sokkal kényelmesebb csak az autókulcsokat egy akkora dobozban elhelyezni, hogy elférjen benne. Barátod mindent megért majd, amikor kiveszi a kulcsokat a dobozból. Nem kell az egész autót magával vinnie, ha egyszerűen átadhatja a kulcsokat.
Egy személy vs a telefonszáma
Vagy itt egy másik összehasonlítás: egy személy és a telefonszáma. A telefonszám nem a személy, de egy telefonszám segítségével felhívhatja, információt kérhet tőle, vagy utasításokat adhat.
Hasonlóképpen egy hivatkozást használnak az objektumokkal való interakcióhoz. Minden objektum kölcsönhatásba lép egymással hivatkozások segítségével. Ahelyett, hogy "embert cserélnénk", egyszerűen telefonszámot cserélünk.
Amikor értéket adunk egy primitív változóhoz, az értéke másolódik (duplikálódik). Amikor egy referenciaváltozóhoz értéket rendelünk, csak az objektum címét (telefonszámát) másolja át – magát az objektumot nem másolja át.
A hivatkozás még egy előnyt kínál: átadhat egy objektumhivatkozást valamilyen metódusnak, és a metódus képes lesz módosítani (megváltoztatni) az objektumot a rá való hivatkozás használatával, metódusainak meghívásával és az objektumon belüli adatok elérésével.
3. Referenciák hozzárendelése
A referenciaváltozók hozzárendelésekor csak az objektum memóriában lévő címe kerül hozzárendelésre. Maguk a tárgyak nem jelennek meg és nem tűnnek el.
Ezzel a megközelítéssel elkerülhető a nagy mennyiségű memória másolása. Ha nagyon nagy objektumot kell átadni egy metódusnak, akkor csak átadjuk az objektumhivatkozást, és kész. A hivatkozás sokkal kevesebb helyet foglal el.
Az összes referenciaváltozó mérete (típusuktól függetlenül) azonos – 4 bájt (mint egy int). De! Ha az alkalmazás 64 bites Java gépen fut, akkor az összes hivatkozás 8 bájt (64 bit) méretű lesz.
Ráadásul a referenciák csak egymáshoz rendelhetők. Nem módosíthatja a hivatkozásokat, és nem rendelhet tetszőleges értéket a referenciaváltozókhoz:
Kód | Leírás |
---|---|
|
Ez megengedett |
|
De ez nem megengedett |
|
Ez pedig nem megengedett |
4. null
Referencia
És mit tárol egy referenciaváltozó, ha még nincs hozzárendelve semmi?
Null hivatkozást tárol . null
egy speciális Java kulcsszó, ami a hivatkozás hiányát jelenti (üres hivatkozás). Az null
érték bármely referenciaváltozóhoz hozzárendelhető.
Minden referenciaváltozó, null
hacsak nincs hozzájuk rendelve valamilyen hivatkozás.
Példák:
Kód | Leírás |
---|---|
|
A String name változó alapértelmezett értéke: null . A int age változó alapértelmezett értéke: 0 . |
Azok a helyi változók, amelyekhez nem rendeltek értéket, mind a primitív, mind a referenciatípusok esetében inicializálatlannak minősülnek.
Ha egy változó valamilyen objektumra való hivatkozást tárol, és törölni szeretné a változó értékét, akkor csak nulla hivatkozást rendeljen hozzá.
Kód | Leírás |
---|---|
|
s üzletek null . s hivatkozást tárol egy karakterlánc objektum s tárolja null . |
5. Hivatkozások átadása a módszerekre
Ha egy metódus referencia típusú paraméterekkel rendelkezik , akkor az értékek ugyanúgy kerülnek átadásra a metódusnak, mint amikor nem referencia változókkal dolgozunk. A paraméterhez egyszerűen hozzárendeljük a másik változó értékét.
Példa:
Kód | Leírás |
---|---|
|
A fill kitölti az átadott tömböt ( array ) az átadott értékkel ( value ). |
A fill
metódus meghívásakor a array
paraméter hivatkozást kap a tömbhöz data
. A value
változóhoz egy hivatkozás van hozzárendelve a karakterlánc objektumhoz ("Hello").
Így néz ki a memória a metódus meghívása előtt fill
:
Így néz ki a memória, amikor a fill
módszer fut :
A data
és array
változók ugyanarra a tárolóra vonatkoznak (hivatkozásokat tárolnak) a memóriában.
A value
változó a string objektumra ( ) való hivatkozást tárolja "Hello"
.
A tömb cellái is csak hivatkozásokat tárolnak az objektumra "Hello"
.
Valójában egyetlen objektum sem duplikálódik – csak a hivatkozások másolódnak.
6. Összehasonlítás a C/C ++ nyelvvel
Az interjúkban néha megkérdezik a Java programozókat, hogyan továbbítják az adatokat a Java metódusaihoz? És néha az a kérdés, hogy az adatokat referencia vagy érték alapján adják át?
Ez a kérdés a C++-ból származik, de Java-ban nem túl értelmes . Java-ban a paraméterekhez mindig egyszerűen az argumentumok értékeit rendeljük hozzá. Tehát a helyes válasz az " érték szerint ".
De készüljön fel arra, hogy elmagyarázza álláspontját , mert azonnal hallhatja a visszavágást: "A primitív típusokat érték, a referenciatípusokat pedig hivatkozás adja át."
Ez a probléma abból a tényből ered, hogy sok Java programozó korábban C++ programozó volt. Ebben a programozási nyelvben nagyon fontos volt a paraméterek metódusoknak való átadásának kérdése.
A Java-ban minden egyértelmű: a primitív típusok értékeket tárolnak, és a referenciatípusok is tárolnak egy értéket – egy hivatkozást. Kérdés, hogy egy változót értéknek tekintünk- e .
A C++ nyelvben egy változó egy objektumra való hivatkozást és magát az objektumot is tárolhatja. Ugyanez igaz a primitív típusokra is: egy primitív változó tárolhat egy értéket, vagy deklarálhatja a változót hivatkozásként egy int
. Tehát a félreértések elkerülése érdekében a C++ programozók az objektumot egy hivatkozásra mindig hivatkozásként , magát az objektumot pedig értékként hivatkozzák.
A C++ nyelvben könnyen előfordulhat, hogy az egyik változó tartalmaz egy objektumot, de a másik egy hivatkozást tartalmaz arra az objektumra. Ennek megfelelően nagyon fontos volt a kérdés, hogy egy változó mit tárol – magát az objektumot vagy csak egy hivatkozást rá. Amikor egy objektumot átadtak egy metódusnak, a rendszer átmásolta (ha érték alapján adta át), és nem másolta (ha hivatkozással adta át).
Java-ban ez a kettősség nem létezik, így a helyes válasz: az argumentumok érték alapján kerülnek átadásra a Java metódusoknak . Csak arról van szó, hogy amikor referenciaváltozókról beszélünk, ez az érték referencia.
GO TO FULL VERSION