English version is at DZone
Java 1.5 öncesinde primitive tipler, reference tiplerinden tamamen farklıydı. Ama artık autoboxing kavramıyla, bu farkın ortadan kalkması, birçok sorunu da beraberinde getirmiştir.
Java 1.5 öncesinde primitive tipler, reference tiplerinden tamamen farklıydı. Ama artık autoboxing kavramıyla, bu farkın ortadan kalkması, birçok sorunu da beraberinde getirmiştir.
Bu sorunlardan birini aşağıdaki kod parçası ile açıklayalım:
import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; public class SetAndList{ public static void main(String[] args) { Set<Integer> set = new TreeSet<Integer>(); List<Integer> list = new ArrayList<Integer>(); for (int i = -2; i < 3; i++) { set.add(i); list.add(i); } for (int i = 0; i < 3; i++) { set.remove(i); list.remove(i); } System.out.println(set + " " + list); } }
Birçoğumuz yukarıdaki kod parçasının çıktısının aşağıdaki
gibi olacağını düşünebiliriz:
[-2, -1] [-2, -1]
Ama maalesef kod düşündüğümüzden farklı bir şekilde
çalışarak, aşağıdaki çıktıyı üretecektir:
[-2, -1] [-1, 1]
Yukarıdaki durumun, Java 1.5 ile
hayatımıza giren “autoboxing” özelliği ile “overloading” kavramlarının
dikkatsiz kullanımından kaynaklandığını söyleyebiliriz.
Yukarıdaki koddaki “set.remove(i)”
satırı ile, “remove(E)” methodu çağrılmaktadır. Buradaki “E”,
set’in element tipi olan “Integer”’dır ve int değeri auotoboxing ile Integer
değere çevrilir. Bu da beklediğimiz bir durumdur, yani kod set’in içindeki
pozitif değerleri set’ten çıkarır.
Diğer taraftan, koddaki “list.remove(i)”
satırı, overload edilen “remove(int i)” methodunu çağırır. Bu method ise,
listedeki belirtilen posizyondaki değeri siler. Yani yukarıdaki kod, "list”
’ in içeriğinin [ -2, -1, 0, 1, 2 ] olduğu durumda, önce “0” pozisyonundaki,
sonra “1” ve sonra da “2” poziyonundaki değeri listeden çıkarır. Sonunda
listenin içeriği [-1, 1] olarak kalır. Buradaki karışıklığı önlemek için, “list.remove(i)”
satırındaki i’yi Integer’a cast ederek doğru overload edilmiş methodun
çağrılmasını sağlayabiliriz.
for (int i = 0; i < 3; i++) { set.remove(i); list.remove((Integer)i); // veya list.remove(Integer.valueOf(i)); }
Bu düzeltmeden sonra, kodumuz
beklediğimiz gibi aşağıdaki çıktıyı verebilir:
[-2, -1] [-2, -1]
Yukarıdaki karışıklığın nedeni,
compiler’ın List interface’inin overload edilen iki adet remove
methodunu(remove(E) ve remove(int)) autoboxing özelliği nedeniyle karıştırmış
olmasından kaynaklanmaktadır. Java 1.5 sonrası, generic ve autoboxing
kavramları, List interface’ini bozdu diyebiliriz.
Buradan çıkaracağımız dersleri aşağıdaki
gibi özetleyebiliriz:
Yukarıdaki maddelere dikkat etmediğimiz durumda, methodları kullanacak kişilere çok dikkatli olmaları gerektiğini anlatmamız gerekecektir. Aksi halde methodların neden çalışmadıklarını anlamakta zorlanacaklardır.
- Java class’larımızdaki method’larımızı overload edebiliyor olmamız, onları overload etmemiz gerektiği anlamına gelmemektedir.
- Genel olarak, aynı sayıda parametre içeren methodlarımızı overload etmekten kaçınmamız, yani methodlarımız için anlamlı ve farklı isimler kullanmamız gerekmektedir. İlla bu şekilde yapmamız gerekiyorsa da, methodların aynı parametrelerde, aynı davranışı göstermelerine dikkat etmemiz gerekmektedir.
Yukarıdaki maddelere dikkat etmediğimiz durumda, methodları kullanacak kişilere çok dikkatli olmaları gerektiğini anlatmamız gerekecektir. Aksi halde methodların neden çalışmadıklarını anlamakta zorlanacaklardır.
Yararlandığım Kaynaklar
Efective Java 2nd Edition, J. Blochali kemal taşçı
Hiç yorum yok:
Yorum Gönder