18 Mart 2009 Çarşamba

Bir problemim var "String" ile...

Geçen gün bir hata ayıklama - debug - işlemi sırasında bir String tipinde nesneyi split fonksiyonu ile parçalara ayırdığınızda, bu parçalardan her birinin asıl nesnenin değerinin bir kopyasını da taşıdığını gördüm.

Aslında bunun böyle olduğunu ilk başta anlamadım. :)

İlk aklıma gelen soru şu idi: Alla alla nasıl olurda parçaladığım nesnenin değeri her bir parçanın içinde bulunur ve parçaların değerleri ile value özelliği - attribute - aynı değeri taşımaz?

Yani nesne değeri başka , nesne.value -> String.value <- değeri başka mı ? Nasıl olurda String tipinde bir nesne split fonksiyonuyla n adet parçaya ayrılır ve bu parçalardan her biri olan String tipindeki nesnecikler asıl nesnenin - parçaladığımız nesne - değerini taşır?



Yukarıda bu hata ayıklama işlemini görebilirsiniz.

Sonra şu aklıma geldi: Bir parçadan asıl nesnenin değerine ulaşabilir miyim?
Evet bu fikir takıldı kafama ve uyuyamayacaktım ben de araştırmaya başladım internette...

Bu değeri nasıl alabilirdim? Ve bu değer neden nesnenin parçalarında bulunuyordu?
Sonra Allah'a şükür etmek istiyorum ki; java iyi ki açık kaynak kod - open source -.
OpenJDK'dan java.lang.String nesnesinin kaynak kodunu buldum.

Evet anahtar özellik "private final char value[];". Bu özellik eğer String tipinde bir nesne oluşturulunca değerinin bir kopyası value de tutuluyor olması. :) İşte sorumun cevabına yaklaşma anı! Ancak bu value private :) yani ben nasıl ulaşabilirim bu özelliğin değerine?

Evet onun cevabı da Reflection ...

Aşağıdaki kod parçasıyla bu değeri almayı başardım:


String msg = "*141#3#123455666656564645#";
StringTokenizer st = new StringTokenizer(msg, "*");
String ilk = st.nextToken();
StringTokenizer st2 = new StringTokenizer(ilk, "#");
String ikinci = st2.nextToken();
String ucuncu = st2.nextToken();
String aman = "tamam";

Class t = String.class;
Field f = t.getDeclaredField("value");
f.setAccessible(true);
System.out.println(f.get(ucuncu));
System.out.println(f.get(ikinci));
System.out.println(f.get(ilk));
System.out.println(f.get(msg));
System.out.println(f.get(aman));


Peki bunu başardım ama bu String nesnesini parçaladım bir örüntüye göre - pattern - ancak hepsinde asıl nesnenin değerinin olması biraz pahalı bir işlem değil miydi?

Yani value private final idi...
Her parça aynı nesnenin value özelliğine bir adres ile işaret etmiyorsa - pointer - bu kadar hafızayı boş yere heba etmenin ne anlamı vardı? GC'ye o kadar güveniyorlardı yani?

Yukarıda verdiğim java kodunu çalıştırırsanız enterasan bir sonuç çıkıyor:


System.out çıktıları:

[C@addbf1
[C@addbf1
[C@addbf1
[C@addbf1
[C@42e816

burada farklı olan [C42e816 yani yeni bir String tipinde nesnedir. Diğerleri ise split ile parçlanmış nesnenin parçacık nesneleri ...

Ve aynı özelliği -
value - paylaşıyorlar!

Hem private final bir özellik ve hem de parçalara ayrılmış nesnenin tüm parçacık nesnelerinde aynı tip dolayısıyla aynı değer !

Neyse sonunda bazı şeyleri çözmüş ve rahatlamış olarak uyudum.
Anlamış olmasamda...

Hiç yorum yok: