Merhaba Arkadaslar,
Bir kac yazi boyunca Java’da Wrapper siniflari inceledik. Hatirlayacagimiz gibi Overloading konusunu onceki yazilarda incelemistik fakat daha derinlemesine inceleyecegimizi belirtmistim , bu yazida Overloading konusunu isin icine Wrapper siniflari ve Var-args degiskenlerini de katarak inceleyecegiz.
Overloading konusunun trickly olmasina neden olacak bir kac maddemiz sunlar olacak ;
- Widening
- Autoboxing
- Var-args
Oncelikle kucuk bir hatirlatma icin basit bir kod ornegimizi gorelim ;
public class CoolClass { static void coolMethod(int x) { System.out.print("int "); } static void coolMethod(long x) { System.out.print("long "); } static void coolMethod(double x) { System.out.print("double "); } public static void main(String[] args) { byte b = 10; short s = 10; long l = 10; float f = 5.0f; coolMethod(b); coolMethod(s); coolMethod(l); coolMethod(f); // int int long double } }
dikkat edecek olursak byte tipindeki b degikseni ile short tipindeki s degiskeni int tipinde parametre alan metoda sorunsuzca gittiler. long tipindeki l degiskeni ise int tipinde parametre alan metoda gidemez , long tipinde degisken alan metoda gider, ayrica long tipinde bir degisken alan metot olmasaydi double turunde degisken alan metoda da gidebilir. benzer sekilde f degiskeni float turundedir ve double turunde parametre alan metoda sorunsuzca gidebilir. Tam bir eslesme durumu olmadiginda, JVM , en kucuk argumanli uygun metod ile esletirme yapar ve cagirir. not: bu noktayi anlamak acisindan bol miktar deneme kod yazilmalidir. Simdi bir baska test sinifi yazalim ve su sekilde olsun;
public class Test { static void go(Integer x) { System.out.println("Integer"); } static void go(long x) { System.out.println("long"); } public static void main(String[] args) { int i = 10; go(10); } }
int tipinde bir degiskenimiz var, go metodunu cagirdigimizda Integer degil long parametre alan metodumuz cagrilir. Java, boxing (int ten Integer’a donusum) yerine widening (int — >long ) islemini tercih eder. Simdi de var-arg metod iceren basit bir ornek inceleyelim ;
public class Test2 { static void go(int x, int y) { System.out.println("int,int"); } static void go(byte... x) { System.out.println("byte ..."); } public static void main(String[] args) { byte b = 10; go(b, b); } }
go(b,b) metodumuz int,int paremetresi alan metodu cagiracaktir. Bu iki ornekten sunlari cikartabiliriz;
- Widening , boxing den daha onceliklidir.
- Widening , var-args tan daha onceliklidir.
Bir diger durum olarak Boxing ve Var-args yapisini inceleyelim ;
public class Test3 { static void go(Byte x, Byte y) { System.out.println("Byte,Byte"); } static void go(byte... x) { System.out.println("byte ..."); } public static void main(String[] args) { byte b = 10; go(b, b); //Byte,Byte } }
go(b,b) metodumuz Byte, Byte parametre alan metodu cagiracaktir. Buradan da anlayabilecegimiz gibi ;
- Boxing , Var-args tan daha onceliklidir.
Widening Reference Variable
Simdi de referans tipinde degiskenlerin widening durumlarini inceleyelim;
class Animal { } class Dog extends Animal { } public class Test5 { public static void main(String[] args) { Dog d = new Dog(); go(d); } static void go(Animal a) { System.out.println("Animal"); } }
Buna benzer ornek kodlari daha once incelemistik, Dog IS-A Animal oldugu icin Animal parametre alan metoda sorunsuzca gidebilir.
Bu konuyla ilgili bir ornek daha inceleyelim ;
public class Test4 { static void go(Number n) { System.out.println("Number"); } static void go(short s) { System.out.println("short"); } public static void main(String[] args) { Short s = 10; go(s); } }
Short tipinde degiskenimiz var, short parametreli metot mu Number parametreli mi metot cagrilir ? Widening islemi mantigi burada da uygulanacaktir ve Number parametreli metot cagrilacaktir. ( Short IS-A Number)
not : Asagidaki ornek yapiyi dikkalice inceleyin ve bu konuda bol miktarda ornek kod yazin
Short s=10; Short>Number>Object>short>int>long>short...>int...
Onceki yazilarda Wrapper siniflarin hiyerarsik bir tablosunu incelemistik, ornegin Short IS-A Integer diyemeyiz !
public class Test6 { public static void main(String[] args) { Short s = 10; // go(s); // compiler errror } static void go(Integer x) { System.out.println("Integer"); } }
Byte , Short’a ya da Integer’a ya da Short Integer’a vb genisletilemez.(widening)
Combining Widening and Boxing
Simdide widening ve boxing isleminin ayni anda gerektigi durumlari inceleyelim ;
public class Test7 { static void go(Short s) { System.out.println("Short"); } public static void main(String[] args) { byte b = 10; // go(b); // once byte tipinden short tipine widening islemi uygulanmali // sonrasinda Short tipine boxing uygulanmali, fakat bu durum illegaldir // derleme hatasina yol acar } }
once byte tipinden short tipine widening islemi uygulanmali sonrasinda Short tipine boxing uygulanmali, fakat bu durum illegaldir derleme hatasina yol acar.
Pei Short tipinde parametre yerine Object tipinde parametre olarak degistirecek olrusak ;
public class Test8 { static void go(Object o) { Byte b2 = (Byte) o; System.out.println(b2); } public static void main(String[] args) { byte b = 10; go(b); } }
Bu sefer sorunsuzca calisacaktir. byte tipinden Byte tipine Boxing islemi olacaktir daha sonrasinda Byte tipinden Object tipine widening islemi olacaktir. ( Byte Is -A Object)
not: asagidaki sekilde parametreler alan metotlari birbiriyle karsilastirip bol miktar kod yazmayi ihmal etmeyin.
byte b=10; byte>short>int>long>Short>Number>Object
Combination with Var-args
Son olarak Var-args ile ilgili kucuk bir ornek kod daha yazalim ;
public class Test9 { static void wide_varargs(long... x) { System.out.println("long...."); } static void box_varargs(Integer... x) { System.out.println("Integer...x"); } public static void main(String[] args) { int i=10; wide_varargs(i); box_varargs(i); } }
i int tipinde degiskenimiz , 1.metotda widening islemine 2.metotda ise boxing islemine tabi tutulur ve sorunsuzca calisir.
- Primitive widening mantik olarak en kucuk parametreli metodu kullanir.
- Bir Wrapper siniftan diger Wrapper sinifa widening islemi yapilamaz ( IS-A sartini saglamaz ! )
- Bir primitive tipteki degisken widening ten sonra boxing islemine tabi tutulamaz.( int , Long olamaz)
- Once boxing islemi sonrasinda widening islemi yapilabilir. (int , Integer, Object)
- Var-arg degiskenleri widening veya boxing islemlerine tabi tutabiliriz.
Yazimi burada sonlandiriyorum. Bu yaziyi bir kac defa okumak ve burada yazilanlarin bir kac kati kadar ornek kod yazmak faydali olacaktir.