"Enter"a basıp içeriğe geçin

Referanslar

 

Çalıştırdığımız programlar, daha hızlı olduğu için RAM belleğe yüklenir. RAM bellek aslında 2 temel kısımdan oluşur. Bunlar stack ve heap’tir. Program çalıştığında boyutu bilinen değerler stack kısmında tutulur. Ancak new ile dinamik bir şekilde değişken oluşturuyorsak, heap kısmında tutulur. Bu durum derleyicinin optimizasyonuna göre ufak değişiklikler gösterebilir.

Java’daki veri tipleri

Java’da 2 tip veri vardır. Bunlar Primitive ve Referanslı tiplerdir. İnt, float, boolean gibi temel veri tiplerine Primitive denir. Temel veri tipleri hafızada stack üzerinde tutulurlar. Bir fonksiyona kopyalandıklarında değerleri kopyalanarak geçer. Yani asıl değişkenimiz değişmez.

Referanslı veri tipleri ise sınıflar ve Array’lerdir. Yani new ile yer aldığımızda, dinamik bellek olan heap üzerinde bir yer ayırmış oluruz. Ama bu yer hafızanın herhangi bir bölgesinden ayrılabilir.

Ayrılan yerin hafızadaki konumunu tutmak için referansları kullanırız. Yani artık kodumuzun bir yerinde oluşturduğumuz bu değişkeni kullanmak istediğimizde referansı üzerinden erişmemiz gerekir. Referanslar da genellikle stack üzerinde tutulurlar.

referans önceden oluşturulmuş olabilir.

Person tipinde bir referans oluşturduk. new ile Person tipinde bir nesne için yer aldık ve “İlhan” ile ilklendirdik. Ve oluşturduğumuz anda da bu yeri işaret etmek için adresini referansa verdik.
Artık oluşturduğumuz bu nesneye erişmek için person1 referansını kullanabiliriz.
(Standart tipleri tutan değişken adları referans değildir!!!)

Bir nesneyi hafızada oluşturduğumuz anda referans ile tutmamız gerekir. Eğer sadece new ile oluşturursak ve referans ile adresini tutmazsak, artık ayrılan o alanın adresini bulmamız mümkün değildir. Ve bu nesneyi kullanamayız.

Aynı nesneyi 2 farklı referans ile tutabilir.

Birinde yapılan değişiklik diğerini etkiledi.

Eğer sadece değeri kopyalamasını istiyorsak copy constructor eklememiz gerekir.

Artık referanslar kopyalanmıyor
Hafızada yeni bir yer alındı ve person1’in gösterdiği adreste bulunan nesnenin üyeleri bu yeni alınan yere kopyalandı. Sonra bu alınan yeri göstermesi için person2 referansı oluşturuldu.
person1 ile person2 farklı yerleri gösterdiğinden, birinde yapılan değişiklik diğerini etkilemez.

Bir referansın gösterdiği adresi sonradan değiştirebiliriz. Ancak eğer başka bir referans tarafından da tutuluyorsa, önceki nesneyi gösteren bir referans kalmadığı için, o nesneye bir daha erişemeyiz.

Fonksiyona referans gönderme

Eğer bir nesneyi fonksiyona göndermek istersek, referansını yollamamız gerekir. Aslında referans da kopyalanır. Ama referansın içindeki şey bir adres olduğundan, aynı adresi gösteren 2 referans elde etmiş oluruz. Yani birinde yapılan değişiklik diğerini etkiler.

person1 referansı person2’ye kopyalandı. Artık aynı yeri gösteriyorlar.

Referans döndürme

Bir fonksiyonun içindeki değişkenlerin ömrü, fonksiyon bitene kadardır. Bu durumda bir fonksiyonun içinde oluşturduğumuz referanslar da fonksiyon bittiğinde silinecektir.
new ile aldığımız yeri referans ile tuttuğumuz için, eğer referans silinirse o nesneye bir daha ulaşamayız.

Eğer fonksiyonun içinde oluşturduğumuz yerin silinmemesini ve o fonksiyon dışında da kullanılabilmesini istiyorsak, referans olarak döndürmemiz gerekir.
Fonksiyon dönen şey = ile kopyalanacaktır. Bu durumda nesnenin adresi de kopyalanmış olur ve nesne ölmez.

Wrapper Class’lar

Bazen temel veri tiplerinin de referans ile tutulması gerekebilir. Özellikle ileride göreceğimiz arraylist, linkedlist gibi veri yapılarında veri tiplerinin referans ile tutulmasına ihtiyaç duyarız.

Temel tiplerin referanslarının oluşturulması için wrapper class’lar oluşturulmuştur. Wrapper class nesneleri, aynı normal bir nesne oluşturur gibi oluşturulur.

Wrapper class nesnesini oluşturulken içine int değerimizi göndeririz. Böylece int değerimiz bir değişken ile değil, referans ile tutulmuş olur.

Integer a=new Integer(5);

 

 

 

 

Beklediğimiz gibi bir sonuç alamadık. Çünkü wrapper referanslar değişmez olarak tanımlanır.Eğer bir wrapper referansı ile += *= gibi işlemler yaparsak, mevcut içeriği değiştirmez. Yeni bir adrese yeni değeri yazar. Yani Integer i dediğimizde b’nin adresi kopyalandı. i’yi yazdırdığımızda b’nin içindeki değer yazıldı. Ancak i+=5; dediğimizde i hafızada başka bir yer göstermeye başladı. Yani b ile i birbirinden bağımsız oldu. Birindeki değişiklik diğerini etkilemez. Ama bu durum kafanızı çok karıştırmasın.

Wrapper sınıflara, uygun olduğu sürece string ile de değer verilebilir.
Eskiden bu tip dönüşümlerinde valueOf() methodunu kullanırdık. Ancak yeni java sürümlerinde bu işlemi otomatik gerçekleştiriyor.

 

Sonuç olarak, eğer temel veri tiplerini referans ile tutmamız gerekiyorsa wrapper sınıfları kullanırız. Wrapper sınıfların bazı sıkıntıları olsa da, bunları otomatik çözecek mekanizmalar eklenmiştir.

Diğer veri tipleri için referans türleri şöyledir:

byte=Byte
short=Short
long=Long
float=Float
double=Double
char = Character

referans gerektiren yerlerde bunları kullanabiliriz.

 

 

    Bir cevap yazın

    E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir