Metode Overloading untuk argumen nol

133

Saya telah menambahkan tiga metode dengan parameter:

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");
}

Ketika saya menelepon doSomething(null), maka kompiler melempar kesalahan sebagai metode ambigu . Jadi adalah masalah karena Integerdan char[]metode atau Integerdan Objectmetode?

Phani
sumber
3
Ubah saja Integerke int.
Mudassir
2
@Mudassir: dan apa yang akan dipecahkan?
Joachim Sauer
2
@ Joachim Sauer: Jika diubah dari Integer ke int, maka null tidak disebut tipe primitif di Jawa, sehingga kompiler tidak akan melempar kesalahan.
Phani
@ Joachim Sauer: Tidak akan membuang reference to doSomething is ambiguouskesalahan.
Mudassir

Jawaban:

211

Java akan selalu mencoba menggunakan versi metode yang paling spesifik dan berlaku yang tersedia (lihat JLS §15.12.2 ).

Object, char[]dan Integersemuanya dapat dianggap nullsebagai nilai yang valid. Oleh karena itu ketiga versi ini dapat diterapkan, jadi Java harus menemukan yang paling spesifik.

Karena Objectmerupakan super-type char[], versi array lebih spesifik daripada versi-nya Object. Jadi jika hanya dua metode itu ada, char[]versi akan dipilih.

Ketika kedua versi char[]dan Integertersedia, maka keduanya lebih spesifik daripada Objecttetapi tidak ada yang lebih spesifik dari yang lain, jadi Java tidak dapat memutuskan mana yang akan dipanggil. Dalam hal ini, Anda harus menyebutkan secara eksplisit mana yang ingin Anda panggil dengan melemparkan argumen ke jenis yang sesuai.

Perhatikan bahwa dalam praktiknya masalah ini terjadi jauh lebih jarang daripada yang diperkirakan orang. Alasan untuk ini adalah bahwa itu hanya terjadi ketika Anda secara eksplisit memanggil metode dengan nullatau dengan variabel dari tipe yang agak tidak spesifik (seperti Object).

Sebaliknya, doa berikut akan sangat jelas:

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

Meskipun Anda masih memberikan nilainya null, Java tahu persis metode mana yang harus dihubungi, karena itu akan memasukkan jenis variabel ke dalam akun.

Joachim Sauer
sumber
1
Ini dinyatakan untuk Java 7. Apakah itu juga berlaku untuk versi Java sebelumnya? Maksud saya: Jika Anda memiliki beberapa tanda tangan metode dengan parameter hanya sepanjang hierarki jenis, daripada Anda berada di sisi save dengan null sebagai nilai aktual? Dan jika Anda telah membangun "hierarki untuk" seperti dalam contoh di sini, maka Anda tidak?
Christian Gosch
2
Saya cukup yakin aturan-aturan itu sama untuk setidaknya semuanya sejak Java 1.1 (kecuali untuk penambahan obat generik, jelas).
Joachim Sauer
Apakah ini berarti bahwa jika kompiler harus memilih di antara doSomething (String str) dan doSomething (Object obj) selama runtime dengan doSomething (null), doSomething (String str) akan dipanggil.
Sameer
42

Setiap pasangan dari ketiga metode ini ambigu dengan sendirinya ketika dipanggil dengan nullargumen. Karena setiap tipe parameter adalah tipe referensi.

Berikut ini adalah tiga cara untuk memanggil satu metode spesifik Anda dengan nol.

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

Bolehkah saya menyarankan untuk menghapus ambiguitas ini jika Anda benar-benar berencana untuk memanggil metode ini dengan nullargumen. Desain seperti itu mengundang kesalahan di masa depan.

jmg
sumber
1
Hanya Integer- char[]pasangan yang ambigu, karena dalam dua kasus lain, kompiler Java dapat memilih pilihan yang paling spesifik, seperti yang dijelaskan @ JoachimSauer.
kajacx
1
@ kajacx: ​​Pertanyaan awal OP adalah tentang memanggil metode ini dengan nullsebagai parameter. Di bawah prasyarat itu, ketiga pasangan bersifat ambigu. Untuk kasus umum, saya setuju bahwa hanya Integer - char[]pasangan yang ambigu.
jmg
bagaimana doSomething(null)untuk public static void doSomething(String str) { System.out.println("String called"); } ini akan kembali string disebut.
Sameer
Apakah mungkin untuk menggunakan anotasi seperti "nullable" atau "not nullable" dan mengatur deklarasi sehingga hanya satu metode yang Anda inginkan untuk mendapatkan null dengan argumen "null" (namun jenis implisit nol) yang eksplisit selalu dipilih dengan jelas kelebihan tertentu ??
peterk
4

nulladalah nilai yang valid untuk salah satu dari ketiga jenis; jadi kompiler tidak dapat memutuskan fungsi mana yang akan digunakan. Gunakan sesuatu seperti doSomething((Object)null)atau doSomething((Integer)null)sebagai gantinya.

Lars Noschinski
sumber
Saya menghapus metode dengan parameter Integer, itu memanggil fungsi dan mengembalikan output sebagai "Array Dipanggil" , jadi apa kontrak antara Array dan Objek ?
Phani
2
Array Java juga Obyek.
Zds
2

Setiap kelas di Jawa memperluas kelas Object. Bahkan kelas Integer juga memperluas Object. Oleh karena itu baik Obyek dan Integer dianggap sebagai instance Objek. Jadi ketika Anda melewatkan null sebagai parameter daripada kompiler menjadi bingung bahwa metode objek mana yang dipanggil yaitu Dengan parameter Objek atau parameter Integer karena mereka berdua objek dan referensi mereka bisa nol. Tetapi primitif di java tidak memperluas Object.

Ankit
sumber
1

Saya telah mencoba ini dan ketika ada tepat sepasang metode kelebihan beban dan salah satunya memiliki objek tipe parameter maka kompiler akan selalu memilih metode dengan tipe yang lebih spesifik. Tetapi ketika ada lebih dari satu jenis tertentu, maka kompiler melempar kesalahan metode yang ambigu.

Karena ini adalah peristiwa waktu kompilasi, ini hanya dapat terjadi ketika seseorang dengan sengaja mengabaikan nol untuk metode ini. Jika ini dilakukan dengan sengaja maka lebih baik membebani metode ini lagi tanpa parameter atau membuat metode lain sama sekali.

Jafar Ali
sumber
0

ada ambiguitas karena doSomething (char [] obj) dan doSomething (Integer obj).

char [] dan Integer keduanya sama-sama superior untuk null itu sebabnya mereka ambigu.

chitrendra chaudhary
sumber
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);
    }
}

Outputnya adalah Int yang disebut null dan ambiguitas dengan char [] dan Integer

nagarjuna chimakurthi
sumber