1. Referans değişkenler

Java dilinde iki tür değişken vardır: ilkel değişkenler ve diğer her şey. Olduğu gibi, şimdi "geri kalan her şey" hakkında konuşacağız.

Aslında ilkel değişkenler ve referans değişkenler var demek daha doğru olur . Peki nedir bu referans değişkenler?

Değişkenleri doğrudan değerleri depolayan ilkel türlerin aksine, başvuru değişkenleri nesnelere yapılan başvuruları depolar. Yani, bellekte bir yerde bir nesne vardır ve referans değişkeni basitçe bu nesnenin adresini bellekte saklar (nesneye bir referans).

Yalnızca ilkel türler, değerleri doğrudan değişkenlerin içinde depolar. Diğer tüm türler yalnızca bir nesne başvurusunu saklar . Bu arada, zaten iki tür değişkenle karşılaştınız - Stringdeğişkenler ve dizi değişkenleri.

Hem bir dizi hem de bir dize, bellekte bir yerde depolanan nesnelerdir. Stringdeğişkenler ve dizi değişkenleri yalnızca nesnelere yapılan başvuruları depolar.

Java'daki referans değişkenleri

int a, int b and double ddeğerlerini kendi içlerinde saklayan ilkel değişkenlerdir.

Değişken bir String strreferanstır ve adresi (referans) bir Stringnesneye bellekte saklar.

İlkel türdeki bir değişkene ilkel bir değer atarken, değeri kopyalanır (çoğaltılır). Bir referans değişkeni atanırken, yalnızca nesnenin adresi kopyalanır - nesnenin kendisi kopyalanmaz .


2. Referanslar ne hakkındadır?

Referans değişkenler ile ilkel değişkenler arasındaki temel fark nedir?

İlkel bir değişken bir kutu gibidir: içinde bir miktar değer saklayabilirsiniz. Bir referans değişkeni, üzerinde telefon numarası bulunan bir kağıt parçası gibidir.

Bir araba vs arabanın anahtarları

Arkadaşınıza doğum günü için bir araba vermeye karar verdiğinizi hayal edin. Bir kutuya sarıp yanınızda taşımayacaksınız: araba bunun için çok büyük.

Sadece araba anahtarlarını içine alacak kadar büyük bir kutuda sunmak çok daha uygundur. Arkadaşınız anahtarları kutudan çıkardığında her şeyi anlayacaktır. Anahtarları kolayca teslim edebileceğiniz zaman tüm arabayı yanınızda taşımanıza gerek kalmaz.

Bir kişi ve onun telefon numarası

Veya işte başka bir karşılaştırma: bir kişi ve onun telefon numarası. Telefon numarası kişi değildir, ancak telefon numarası onu aramak, ondan bilgi istemek veya talimat vermek için kullanılabilir.

Benzer şekilde, bir nesneyle etkileşim kurmak için bir referans kullanılır. Tüm nesneler, referansları kullanarak birbirleriyle etkileşime girer. "Kişileri değiş tokuş etmek" yerine, sadece telefon numaralarını değiş tokuş ediyoruz.

İlkel bir değişkene bir değer atarken, değeri kopyalanır (çoğaltılır). Bir referans değişkene bir değer atarken, sadece nesnenin adresi (telefon numarası) kopyalanır - nesnenin kendisi kopyalanmaz.

Bir referans bir avantaj daha sunar: bir nesne referansını bir yönteme iletebilirsiniz ve yöntem, nesneye yapılan başvuruyu kullanarak, yöntemlerini çağırarak ve nesnenin içindeki verilere erişerek nesneyi değiştirebilir (değiştirebilir).


3. Referans atama

Referans değişkenleri atanırken, yalnızca nesnenin bellekteki adresi atanır. Nesnelerin kendileri görünmez veya kaybolmaz.

Bu yaklaşım, büyük miktarda belleğin kopyalanmasını önler. Bir metoda çok büyük bir nesne iletmeniz gerekirse, biz sadece nesne referansını iletiriz, o kadar. Referans çok daha az yer kaplar.

Referans atama

Tüm referans değişkenlerinin boyutu (türlerinden bağımsız olarak) aynıdır - 4 bayt (int gibi). Ancak! Uygulamanız 64 bit Java makinesinde çalışıyorsa, tüm referansların boyutu 8 bayt (64 bit) olacaktır.

Ayrıca referanslar sadece birbirlerine atanabilir. Referansları değiştiremez veya referans değişkenlerine rasgele değerler atayamazsınız:

kod Tanım
String hello = "Hello";
String s = hello;
buna izin verilir
String hello = "Hello";
hello++;
Ama buna izin verilmiyor
String hello = 0x1234;
Ve buna izin verilmiyor

4. nullReferans

Ve kendisine henüz hiçbir şey atanmamışsa bir referans değişkeni neyi saklar?

Boş bir referans saklar . nullreferansın yokluğu (boş bir referans) anlamına gelen özel bir Java anahtar sözcüğüdür. Değer nullherhangi bir referans değişkene atanabilir.

Tüm referans değişkenleri, nullkendilerine bir tür referans atanmış olmadıkça.

Örnekler:

kod Tanım
class Person
{
   public static String name;
   public static int age;
}


Değişkenin String namevarsayılan bir değeri vardır: null.
Değişkenin int agevarsayılan bir değeri vardır: 0.

Bir değer atanmamış yerel değişkenler, hem ilkel hem de referans türleri için başlatılmamış olarak kabul edilir.

Bir değişken, bir nesneye referans depoluyorsa ve değişkenin değerini silmek istiyorsanız, o zaman ona boş bir referans atayın.

kod Tanım
String s = null;
s = "Hello";
s = null;
smağazalar null_ bir dize nesnesine
sbir başvuru saklar .
snull

5. Yöntemlere referansları iletmek

Bir yöntemin referans türleri olan parametreleri varsa , değerler yönteme referans olmayan değişkenlerle çalışırken olduğu gibi iletilir. Parametreye basitçe diğer değişkenin değeri atanır.

Örnek:

kod Tanım
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");
   }
}


fillGeçen diziyi ( array) geçen değerle ( ) doldurur value.

Yöntem fillçağrıldığında, parametreye arraydiziye bir başvuru atanır data. Değişkene value, dize nesnesine ("Merhaba") bir başvuru atanır.

Bu, yöntemi çağırmadan önce belleğin nasıl göründüğüdür fill:

Yöntemlere başvuruları iletmek

Yöntem fill çalışırken bellek şöyle görünür :

Yöntem 2'ye başvuruları iletme

datave değişkenleri array, bellekteki aynı kapsayıcıya başvurur (referansları depolar).

Değişken value, string nesnesine ( "Hello") bir referans depolar.

Dizinin hücreleri ayrıca yalnızca nesneye yapılan başvuruları saklar "Hello".

Aslında, hiçbir nesne kopyalanmaz; yalnızca referanslar kopyalanır.



6. C/C++ dili ile karşılaştırma

Röportajlarda, bazen Java programcılarına verilerin Java'daki yöntemlere nasıl aktarıldığı sorulur. Ve bazen soru, verilerin referansa göre mi yoksa değere göre mi iletildiğidir?

Bu soru C++'dan geliyor, ancak Java'da çok anlamlı değil . Java'da, parametrelere her zaman argümanların değerleri atanır. Yani doğru cevap " değere göre " olacaktır .

Ancak konumunuzu açıklamaya hazırlıklı olun , çünkü hemen şu yanıtı duyabilirsiniz: "ilkel tipler değere göre iletilir ve referans tipler referansa göre iletilir."

Bu sorunun kaynağı, birçok Java programcısının geçmişte C++ programcısı olmasından kaynaklanmaktadır. O programlama dilinde parametrelerin metotlara nasıl aktarıldığı sorusu çok önemliydi.

Java'da her şey açıktır: ilkel türler değerleri depolar ve referans türleri de bir değer - bir referans depolar. Bu, bir değişkenin bir değer olarak kabul edilip edilmediği sorusudur .

C++'da bir değişken, hem bir nesneye hem de nesnenin kendisine yapılan bir başvuruyu depolayabilir. Aynısı ilkel türler için de geçerliydi: İlkel bir değişken, bir değeri saklayabilir veya değişkeni bir int. Bu nedenle, karışıklığı önlemek için, C++ programcıları her zaman bir başvuruya ilişkin nesneye bir başvuru olarak ve nesnenin kendisine - bir değer olarak atıfta bulunur.

C++'da, bir değişkenin bir nesne içerdiği, ancak diğerinin o nesneye bir başvuru içerdiği bir duruma kolayca sahip olabilirsiniz. Buna göre, bir değişkenin neyi sakladığı sorusu - nesnenin kendisi mi yoksa sadece ona bir referans mı - çok önemliydi. Bir nesne bir yönteme iletildiğinde, kopyalandı (değere göre iletildiyse) ve kopyalanmadı (referans olarak iletildiyse).

Java'da bu ikilik yoktur, dolayısıyla doğru yanıt şudur: bağımsız değişkenler Java yöntemlerine değere göre iletilir . Sadece referans değişkenlerinden bahsederken bu değer bir referanstır.