Boş bağımsız değişken için Yöntem Aşırı Yükleme


133

Parametreli üç yöntem ekledim:

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

Aradığımda doSomething(null), derleyici belirsiz yöntemler olarak hata atıyor . Yani konudur çünkü Integerve char[]yöntemler veya Integerve Objectyöntemlere?


3
Sadece değiştirmek Integeriçin int.
Mudassir

2
@Mudassir: peki bu tam olarak neyi çözer?
Joachim Sauer

2
@Joachim Sauer: Tamsayı'dan int'e değiştirilirse, Java'da null ilkel türlere atıfta bulunulmaz, bu nedenle derleyici hata vermez.
Phani

@Joachim Sauer: Hatayı atmayacak reference to doSomething is ambiguous.
Mudassir

Yanıtlar:


211

Java, her zaman mevcut bir yöntemin en özel uygulanabilir sürümünü kullanmaya çalışır (bkz. JLS §15.12.2 ).

Object, char[]Ve Integertüm alabilir nullgeçerli bir değer olarak. Bu nedenle 3 sürümün tümü uygulanabilir, bu nedenle Java'nın en spesifik olanı bulması gerekecektir.

Yana Objectsüper türüdür char[], dizi versiyonu daha spesifiktir Object-version. Dolayısıyla, yalnızca bu iki yöntem varsa, char[]sürüm seçilecektir.

Hem char[]ve hem de Integersürümler mevcut olduğunda, ikisi de daha spesifiktir Objectancak hiçbiri diğerinden daha spesifik değildir, bu nedenle Java hangisini arayacağına karar veremez. Bu durumda, bağımsız değişkeni uygun türe çevirerek hangisini aramak istediğinizi açıkça belirtmeniz gerekir.

Pratikte bu sorunun düşündüğünden çok daha nadiren ortaya çıktığını unutmayın. Bunun nedeni, yalnızca nulloldukça spesifik olmayan bir tipte (örneğin Object) bir değişkenle veya bu değişkenle açıkça bir yöntemi çağırdığınızda gerçekleşmesidir .

Aksine, aşağıdaki çağrı tamamen açık olacaktır:

char[] x = null;
doSomething(x);

Değeri hala iletiyor olsanız nullda, değişkenin türünü hesaba katacağı için Java tam olarak hangi yöntemi çağıracağını bilir.


1
Bu Java 7 için belirtilmiştir. Bu önceki Java sürümleri için de geçerli mi? Demek istediğim: Yalnızca bir tür hiyerarşisi boyunca parametrelere sahip birkaç yöntem imzanız varsa, gerçek değer olarak null ile kayıt tarafında olursunuz? Ve buradaki örnekteki gibi bir "hiyerarşi" oluşturduysanız, o zaman değil misiniz?
Christian Gosch

2
Bu kuralların Java 1.1'den beri en azından her şey için aynı olduğundan eminim (tabii ki jeneriklerin eklenmesi dışında).
Joachim Sauer

Bu, derleyicinin doSomething (null) ile çalışma zamanı sırasında doSomething (String str) ve doSomething (Object obj) arasında seçim yapması durumunda doSomething (String str) çağrılacağı anlamına mı gelir.
Sameer

43

Bu üç yöntemin her bir çifti, bir nullargümanla çağrıldığında kendi başına belirsizdir . Çünkü her parametre türü bir referans türüdür.

Aşağıdakiler, belirli bir yönteminizi null ile çağırmanın üç yoludur.

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

Bu yöntemleri gerçekten nullargümanlarla çağırmayı planlıyorsanız, bu belirsizliği ortadan kaldırmanızı önerebilir miyim ? Böyle bir tasarım gelecekte hataları davet eder.


1
Yalnızca Integer- char[]çifti belirsizdir, çünkü diğer iki durumda Java derleyicisi, @ JoachimSauer'in tanımladığı gibi en özel seçeneği seçebilir.
kajacx

1
@kajacx: ​​OP'nin orijinal sorusu bu metotları nullparametre olarak çağırmaktı . Bu ön koşul altında, her üç çift de belirsizdir. Genel durum için, yalnızca Integer - char[]çiftin belirsiz olduğuna katılıyorum .
jmg

peki ya doSomething(null)için public static void doSomething(String str) { System.out.println("String called"); } Bu çağrılan dizeyi döndürür.
Sameer

"Nullable" veya "not nullable" gibi bir anotasyon kullanmak ve bildirimleri ayarlamak mümkün mü, böylece yalnızca bir null almak istediğiniz bir yöntem, böylece açık bir "null" (yine de örtük boş tip) bağımsız değişken her zaman açık bir şekilde seçilir belirli bir aşırı yük?
peterk

4

nullüç türden herhangi biri için geçerli bir değerdir; bu nedenle derleyici hangi işlevi kullanacağına karar veremez. doSomething((Object)null)Veya doSomething((Integer)null)bunun yerine gibi bir şey kullanın.


Yöntemi Tamsayı parametresiyle kaldırdım, işlevi çağırıyor ve çıktıyı "Dizi Çağrıldı" olarak döndürüyor , öyleyse Array ve Object arasındaki sözleşme nedir?
Phani

2
Java dizileri de Nesnelerdir.
Zds

2

Java'daki her sınıf Object sınıfını, Integer sınıfı bile Object sınıfını genişletir. Dolayısıyla hem Object hem de Integer, Object örneği olarak kabul edilir. Dolayısıyla, bir parametre olarak null değerini ilettiğinizde, derleyici hangi nesne yönteminin çağrılacağı konusunda kafa karıştırır, yani Parametre ile Nesne veya parametre Tamsayı, çünkü ikisi de nesne ve başvuruları boş olabilir. Ancak java'daki ilkeller Object'i genişletmez.


1

Bunu denedim ve tam olarak bir çift aşırı yüklenmiş yöntem olduğunda ve bunlardan biri Object parametre türüne sahipse, derleyici her zaman daha özel bir tür yöntemi seçecektir. Ancak birden fazla belirli tür olduğunda, derleyici belirsiz bir yöntem hatası atar.

Bu bir derleme zamanı olayı olduğundan, bu yalnızca biri bu yönteme kasıtlı olarak null geçtiğinde gerçekleşebilir. Bu bilinçli olarak yapılırsa, bu yöntemi parametre olmadan yeniden aşırı yüklemek veya tamamen başka bir yöntem oluşturmak daha iyidir.


0

doSomething (char [] obj) ve doSomething (Integer obj) nedeniyle bir belirsizlik var.

char [] ve Tamsayı, null için aynı üstündedir, bu yüzden belirsizdirler.


0
class Sample{
  public static void main (String[] args) {
       Sample s = new Sample();
       s.printVal(null);

    } 
    public static void printVal(Object i){
        System.out.println("obj called "+i);
    }

    public static void printVal(Integer i){
        System.out.println("Int called "+i);
    }
}

Çıktı, null olarak adlandırılır ve dolayısıyla belirsizlik char [] ve Tamsayı ile olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.