Java'da Overload Çözümlemesi

2015-06-27 21:09:36


Aynı isme fakat farklı sayıda veya farklı tipte parametrelere sahip methodlara aşırı yüklenmiş  metodlar (overloaded methods) diyoruz. Metod çağrısı yaparken, derleyici (compiler) tarafından metodlara geçirdiğimiz parametrelere en uygun olan overload bulunur ve o çağırılır. En uygun metod overload'ının bulunmasına "overload resolution", Türkçe ifade edersek aşırı yükleme çözümlemesi denir. Derleyici çözümleme yaparken aşağıdaki kuralları takip eder:


  • Metoda geçirilen parametrelere birebir uyan bir overload varsa o çağılır
  • Birebir uyan bir overload yoksa en yakın eşleşen çağılır. 
  • Hiçbiri yoksa hata verilir.


Şimdi örneklerle çözümleme işlemini görelim.


package com.kazimsoylu.overloading;

public class Overloading {
	
	public static void main(String[] args) {
		
		int i = 10;	
		test(i);	
	}
	
	public static void test(int i){
		System.out.println("int");
	}
	
	public static void test(long l){
		System.out.println("long");
	}
	
}



Yukarıdaki örnekte test isimli metod int ve long parametre alacak şekilde overload edilmiştir. Bu metodu int tipinde parametre ile çağırdığımızda, derleyici tarafından birebir eşleşen bir overload bulunabiliyor. Bu durumda ekrana "int" yazacaktır.

Peki int parametre alan bir metod olmasa ne olacaktı ? 


package com.kazimsoylu.overloading;

public class Overloading {
	
	public static void main(String[] args) {
		
		int i = 10;	
		test(i);	
	}
	
	public static void test(String s){
		System.out.println("string");
	}
	
	public static void test(long l){
		System.out.println("long");
	}
	
}

Yukarıdaki kodda int tipinde parametre alan bir overload bulunmuyor. Bu durumda int tipinin bir büyük tipine bakılır ve long tipinde parametre alan overload bulunarak ekrana "long" yazılır.

Peki örneğimizi biraz daha değiştirsek neler olacağına bakalım.


package com.kazimsoylu.overloading;

public class Overloading {
	
	public static void main(String[] args) {
		
		int i = 10;	
		test(i);	
	}
	
	public static void test(Integer i){
		System.out.println("Integer");
	}
	
	public static void test(long l){
		System.out.println("long");
	}
	
}

Bu durumda acaba derleyici Integer parametre alan metodu mu yoksa long alan metodu mu çağıracak ? Kodu çalıştırdığımızda ekrana "long" yazdığını görüyoruz. Bunun sebebi de genişletme ( widening ) işleminin autoboxing ( primitive tipten wrapper tipe dönüşüm ) işlemine tercih edilmesidir.  Buradan Java'da Widening ve Autoboxing yazımı okuyabilirsiniz.

Şimdi de aşağıdaki duruma bir göz atalım.

package com.kazimsoylu.overloading;

public class Overloading {
	
	public static void main(String[] args) {
		
		Integer i = 10;	
		test(i);	
	}
	
	public static void test(Number i){
		System.out.println("Number");
	}
	
	public static void test(Long l){
		System.out.println("Long");
	}
	
}

Bu kodu çalıştırdığımızda ekranda "Number" yazdığını görürüz. Wrapper sınıflar arasında genişletme ( widening ) işlemi olmaz. Yani Integer Long'a genişletilmez. Ancak Integer sınıfı Number'dan türediği için Number tipinde parametre olan metod çağrılır.


Biraz da derleyicinin kafasını karıştıralım :)

package com.kazimsoylu.overloading;

public class Overloading {
	
	public static void main(String[] args) {
		
		byte i = 10;	
		byte b = 1;
		test(i,b);	
	}
	
	public static void test(int i,short s){
		System.out.println("int,short");
	}
	
	public static void test(short s, int i){
		System.out.println("short, int");
	}
	
}

Burada ise artık derleyicinin kafası karışıyor ve uygun bir metod bulamıyor. Çünkü ilk parametre olan byte tipindeki i değişkenini mi int yapacak yoksa ikinci değişkeni mi int yapacak, hangisini short yapacak diye ben yazarken bile zorlanırken derleyici ne yapsın :) Bu durumda compile error alıyoruz. Dikkat edersek aldığımız hata derleme zamanı hatası, çalışma zamanı hatası değil ! Çünkü overload çözümleme işlemi derleme zamanında ( compile time ) yapılan bir işlemdir.

İyi çalışmalar....