Satu Nama, Beberapa Versi
Di halaman sebelumnya kamu sudah melihat bagaimana parameter sebuah method menentukan apa yang diterimanya. Method overloading melangkah lebih jauh: kamu bisa memberi nama yang sama ke beberapa method selama daftar parameternya berbeda. Compiler menganggapnya sebagai method yang terpisah dan memilih yang tepat berdasarkan argumen yang kamu kirim.
Itulah sebabnya System.out.println bisa mencetak int, String, boolean, atau double tanpa masalah: tidak ada satu println saja, ada banyak overload yang berbagi nama itu. Kamu menulis panggilan yang kamu maksud, lalu compiler mencocokkannya dengan versi yang sesuai.
Kedua method bernama square, tetapi yang satu menerima int dan yang lain double. Literal 5 adalah int, jadi overload pertama yang berjalan; 2.5 adalah double, jadi yang kedua yang berjalan.
Apa yang Dihitung sebagai Overload Berbeda
Overload harus berbeda di daftar parameternya, artinya minimal salah satu dari ini:
- jumlah parameter yang berbeda,
- tipe parameter yang berbeda, atau
- urutan tipe yang berbeda.
Setiap panggilan punya daftar parameter yang cocok dengan tepat satu dari ketiga method join, jadi tidak ada kebingungan.
Tipe Kembalian Tidak Dihitung
Jebakan yang sering dialami pemula: mencoba melakukan overload hanya berdasarkan tipe kembalian. Tipe kembalian bukan bagian dari signature yang dipakai compiler, jadi kode ini gagal di-compile:
// Does NOT compile - same name, same parameters, only the return type differs
static int value() { return 1; }
static double value() { return 1.0; } // error: value() is already defined
Compiler tidak bisa membedakan keduanya, karena di tempat pemanggilan seperti value() tidak ada argumen yang memberi petunjuk versi mana yang kamu mau. Kamu boleh memberi overload tipe kembalian yang berbeda, tetapi hanya kalau daftar parameternya memang sudah berbeda.
Cara Java Memilih Overload
Kalau lebih dari satu overload bisa menerima argumenmu, Java memilih yang paling spesifik dan lebih mengutamakan tipe yang cocok persis daripada konversi widening (pelebaran tipe). Perhatikan apa yang terjadi dengan argumen int:
show(7) cocok persis dengan int, walaupun long dan double juga bisa menampung 7 setelah widening. Hanya kalau overload yang cocok persis itu dihapus, compiler akan melebarkan int menjadi long, lalu menjadi double. Pemilihan ini sepenuhnya diputuskan saat kompilasi, berdasarkan tipe argumen yang dideklarasikan.
Hati-hati dengan Panggilan yang Ambigu
Kalau tidak ada satu overload yang jelas paling cocok, compiler menolak menebak dan melaporkan error. Ini paling sering terjadi dengan null, yang cocok untuk tipe referensi apa pun:
static void handle(String s) { }
static void handle(StringBuilder b) { }
handle(null); // error: reference to handle is ambiguous
Kedua overload menerima null, dan tidak ada yang lebih spesifik, jadi panggilan itu tidak bisa di-compile. Perbaiki dengan menuliskan tipenya secara eksplisit lewat cast, yaitu handle((String) null), atau dengan merancang ulang agar overload-nya tidak bertabrakan. Kehati-hatian yang sama berlaku saat mencampur autoboxing dan widening; buat kumpulan overload cukup sederhana agar setiap panggilan punya satu pemenang yang jelas.
Overloading Constructor
Overloading tidak terbatas pada method biasa. Constructor sangat sering memakainya untuk menyediakan beberapa cara membuat objek. Constructor tanpa argumen bisa menyerahkan pekerjaan ke constructor yang lebih lengkap dengan this(...):
Kedua constructor berbagi nama Point tetapi berbeda jumlah parameternya, persis seperti method yang di-overload. Mendelegasikan dengan this(...) membuat logika inisialisasi tetap berada di satu tempat.
Overloading vs Overriding
Keduanya terdengar mirip, tetapi tidak berhubungan:
- Overloading: nama sama, daftar parameter berbeda, di class yang sama. Compiler memilih versinya saat kompilasi. Tujuannya menyediakan beberapa varian dari satu operasi.
- Overriding: subclass mendefinisikan ulang method warisan dengan nama yang sama dan parameter yang sama. Java memilih versinya saat runtime berdasarkan tipe asli objek. Tujuannya mengganti perilaku (kamu akan menemuinya di inheritance dan polimorfisme).
Kalau daftar parameternya identik, kamu sedang melakukan overriding (atau memicu error method duplikat di class yang sama); kalau berbeda, kamu sedang melakukan overloading.
Berikutnya: Varargs
Overloading memungkinkan kamu menulis join(a, b) dan join(a, b, c) sebagai method terpisah. Tapi bagaimana kalau kamu ingin menerima argumen dalam jumlah berapa pun tanpa mendeklarasikan overload untuk setiap jumlah? Sintaks varargs di Java memungkinkan satu method menerima daftar argumen dengan panjang yang bervariasi, dan itulah topik halaman berikutnya.
Pertanyaan yang sering diajukan
Apa itu method overloading di Java?
Method overloading adalah mendefinisikan beberapa method dengan nama yang sama di class yang sama, masing-masing dengan daftar parameter yang berbeda (jumlah parameter berbeda, tipe berbeda, atau urutan tipe berbeda). Compiler menentukan versi mana yang dipanggil dengan mencocokkan argumen yang kamu kirim dengan parameter setiap overload. Keputusan ini diambil saat kompilasi, bukan saat runtime.
Bisakah dua method di Java hanya berbeda tipe kembaliannya?
Tidak. Tipe kembalian bukan bagian dari signature method untuk overloading, jadi int total() dan double total() di class yang sama menghasilkan error kompilasi. Overload harus berbeda di daftar parameternya: jumlah, tipe, atau urutan parameter. Tipe kembalian boleh berbeda, tetapi hanya sebagai tambahan dari perbedaan parameter, bukan satu-satunya perbedaan.
Apa perbedaan overloading dan overriding di Java?
Overloading adalah beberapa method dengan nama sama tetapi parameter berbeda di class yang sama, yang dipilih compiler saat kompilasi. Overriding adalah subclass yang mendefinisikan ulang method warisan dengan nama sama dan parameter sama, yang dipilih saat runtime berdasarkan tipe asli objeknya. Overloading menawarkan beberapa varian; overriding mengganti perilaku.