Java – String Pool

The String Pool

Yeni Java programcılarının kafasını karıştırabilecek nitelikte bir optimizasyondan bahsedeceğim. Buna String Pool diyorlar.
En çok kullanılan objelerden biri olan “String”lerin kendi kendilerini optimize etmesi ve daha az yer kaplamasıdır.
Bahsedilmesi gereken önemli bir nokta şudur ki:
Java bunu sadece çift tırnak kullanarak tanıtım yaptığınızda (otomatik olarak) uyguluyor.
Kod parçalarıyla konuyu açıklayalım. Düz anlatım pek başarılı olmuyor.

Buradan şu output’u alırsınız.


Genelde yeni başlayanlara string karşılaştırmalarında “.equals()” metodunu kullanın derler. Çünkü objeleri “==” ile karşılaştırdığımızda onların referanslarını, yani RAM’deki adreslerini karşılaştırır ve aynı içeriğe sahip olsa bile farklı gösterir. Şimdi yukarıdaki output’a tekrar bakın… Orada “==” karşılaştırmamda da true dedi. Açıkça 2 farklı değişken tanıtmış olmama rağmen nasıl bunlar aynı adreste olabilir.
Java’daki önemli bir konsept şudur ki, sizin değişkenleriniz aslında sizin atadığınız değeri tutmaz. (primitive types konusu istisnadır.) Bunlar sadece referans yani adres tutarlar. Gerçekte objenin oluşturulduğu yerin adresini…
String çok sık kullanılan bir veri tipi olduğu için, Java’da şöyle bir durum yapmışlar: Siz
String s=”wax”; şeklinde yani constructor çağırmadan tanıtma yaptığınızda, bundan sonra bir de String d=”wax”; derseniz bu stringi baştan oluşturmuyor. Zaten aynı “wax” bir kere
üretilmiş olduğundan, aynı obje olduğunu anlayınca onun referansını dönüyor. Böylece aynı şey için yeniden yer alınmamış oluyor. Bir string’e yapılan bütün referanslar silinmeden o string silinmediği için ayrıca bir yok olma problemi de doğmuyor. Ne var ki, eğer stringin içeriğini değiştirirsek, adresi de değişiyor.


outputumuz şöyle:


DİYELİM Kİ, siz her nedense bu stringlerin farklı olarak üretilmesini isterseniz, yapmanız gereken şey, bunlardan birini constructor ile oluşturmaktır. Çünkü stringi “new” diyerek oluşturduğunuzda pool’a otomatik ekleme yapılmaz:


Bu kodu çalıştırdığınızda,  “==” karşılaştırmasına false, “equals(…)” karşılaştırmasına true döner.  Yine de biz ikisini de new komutuyla oluşturarak gösterelim.


outputumuz:


YA DA siz atamayı farklı adımlarla yapabilirsiniz.


outputumuz:


BUNUN YANINDA, eğer siz constructor ile oluşturduysanız ve aynı değere sahip başka bir obje oluşturarak yer harcamak istemiyorsanız, bunu yapmanıza yardımcı olacak bir metod var: intern() metodu. Bu metodun yaptığı şeye gelirsek:
-> Stringin tuttuğu değeri poolda(havuzda) arar.
-> Eğer havuzda ZATEN bu değerden varsa havuzdaki objenin adresini döner.
-> Eğer havuzda YOKSA, bu değeri havuza ekler ve sonra adres döner.

Gözlemleyelim:


output:


İlginç, değil mi? Böyle oluyor çünkü zaten “WaxtaP” havuzda var. Constructor ile çağırılan ise, zaten havuza “WaxtaP” olduğu için onun adresini alır. Bir tane de soru soralım:

Aşağıdaki kodda string1==string2 true dönecek mi?


Cevabımız HAYIR. intern() metodu çağrıldı ama ne string1 ne de string2 havuzda.(ikisi de havuzda değil.) intern() metodu burada string2 yi alır ve havuza ekler ama string1 havuzda olmadığı için ikisinin adresleri farklı. O yüzden “==” yaptığımızda false dönüyor.
“==” yaptığımızda true dönmesi için ne yapmalıyız?
Cevabımız çok basit.

Tek satır ekledik yani…


Bu kadarlık kısmı anlatım için yeterli..

Wikipedia’dan bir paragrafın çevirisini ekliyorum.

“…String intern özelliği, bazı modern object-oriented programlama dilleri ve bazı başka dillerde (Python, Ruby, Java ve .NET dilleri, Lisp, Scheme ve Smalltalk gibi) tarafından kullanılıyor….”

daha detaylı incelemek isteyenler için ingilizce wikipedia sayfası http://en.wikipedia.org/wiki/String_interning

Şimdi bazılarının aklıma şöyle bir soru birkaç saniyeliğine takılabilir. “Aynı objeyi gösterirse ben onu kullanırken bir problem çıkmaz mı?”

Cevabını bulamayanlar için ben yazıyorum. Zaten String objeleri immutable yani değiştirilemez olduğu için, sizin her bir değişken için ayrı string oluşturmanıza gerek yoktur. Çünkü hiçbir şekilde zaten üzerinde değişiklik yapamayacaksınız. Diğerleri ile de aynı stringe ulaşsanız bir zararını görmeyeceksiniz.

Java Puzzlers diye bir kitapta da bununla alakalı bir parça yazı geçiyormuş.

“Sizin kodunuz nadiren, çok küçük bir ihtimal dahilinde intern olayına duyarlı olur. intern() olayı sadece JVM’deki hafıza kullanımını düşürmek için dizayn edilmiştir. Programcılara bir araç olarak değil… Objeleri karşılaştırırken == yerine EQUALS metodunu kullanın. Tabi ki objelerin değerlerini değil de adreslerini karşılaştırmak istediğiniz durumlar dışında.” sayfa 30-31’de imiş.

Sanırım bu kadarı yeterlidir
Selametle kalın.

Bu özelliği deneyin ve eğer kaçırdığım veya bilmediğim bir başka noktasını görürseniz lütfen beni de bilgilendirin.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s