4 Aralık 2015 Cuma

Java Notları – Overloading

0 yorum
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.
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:

  • 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. Bloch

ali kemal taşçı