Sering kali satu kata kerja memang wajar dipakai untuk beberapa bentuk masukan: tampilkan() untuk teks, tampilkan(3) untuk angka, tampilkan("Budi", 17) untuk pasangan teks-angka. Java mengizinkan satu class memiliki beberapa method bernama sama selama daftar parameternya berbeda — mekanisme ini disebut method overloading. Kita sudah diam-diam memakainya sejak program pertama: System.out.println adalah method yang kelebihan muatan, dengan versi untuk String, int, double, hingga tanpa argument. Pada Chapter ini kita pelajari aturan overloading, cara compiler javac memilih versi yang tepat, dan satu batas tegas: perbedaan return type saja tidak membuat dua method sah kelebihan muatan.
Method Bernama Sama dengan Parameter Berbeda #
Dua method dinyatakan overload satu sama lain bila nama sama tetapi daftar parameter berbeda — beda jumlah, beda tipe, atau beda urutan tipe. Kombinasi nama dan daftar parameter inilah yang dinamai method signature; signature-lah identitas resmi method di mata compiler. Program berikut menampung enam overload sapa:
public class OverloadSapa {
// Jumlah parameter berbeda
static void sapa() {
System.out.println("Halo!");
}
static void sapa(String nama) {
System.out.println("Halo, " + nama + "!");
}
static void sapa(String nama, String kota) {
System.out.println("Halo, " + nama + " dari " + kota + "!");
}
// Tipe parameter berbeda
static void sapa(int jumlahSiswa) {
System.out.println("Halo kepada " + jumlahSiswa + " siswa!");
}
// Urutan tipe parameter berbeda
static void sapa(String nama, int umur) {
System.out.println("Halo, " + nama + " (" + umur + " tahun)!");
}
static void sapa(int umur, String nama) {
System.out.println("Umur " + umur + " milik " + nama + "!");
}
public static void main(String[] args) {
sapa();
sapa("Budi");
sapa("Budi", "Bandung");
sapa(30);
sapa("Siti", 16);
sapa(17, "Dewi");
}
}Output yang Dihasilkan:
Halo!
Halo, Budi!
Halo, Budi dari Bandung!
Halo kepada 30 siswa!
Halo, Siti (16 tahun)!
Umur 17 milik Dewi!Enam pemanggilan pada main mendarat pada enam method berbeda tanpa tebakan: sapa() tanpa argument menuju overload tanpa parameter; sapa("Budi", "Bandung") menuju overload (String, String); sapa(30) menuju overload int; sedangkan sapa("Siti", 16) dan sapa(17, "Dewi") mengikuti urutan tipenya masing-masing. Nama parameter tidak berperan dalam signature — sapa(String nama, int umur) dan sapa(String teks, int angka) dianggap method yang sama persis.
Compiler Memilih Overload yang Paling Cocok #
Bagaimana bila tidak ada overload yang cocok persis? Compiler melakukan pencarian berjenjang: versi dengan tipe sama persis didahulukan; bila tidak ada, compiler mencari versi yang bisa dipenuhi lewat widening (pelebaran tipe) seperti int ke long atau int ke double. Program berikut memperagakan kedua tahap tersebut:
public class ResolusiTipe {
static String jenis(int nilai) {
return "int : " + nilai;
}
static String jenis(double nilai) {
return "double : " + nilai;
}
static String jenis(String nilai) {
return "String : " + nilai;
}
public static void main(String[] args) {
System.out.println(jenis(7)); // cocok persis dengan int
System.out.println(jenis(7.0)); // cocok persis dengan double
System.out.println(jenis("7")); // cocok persis dengan String
System.out.println(jenis(7L)); // long melebar ke double
System.out.println(jenis((byte) 7)); // byte melebar ke int
}
}Output yang Dihasilkan:
int : 7
double : 7.0
String : 7
double : 7.0
int : 7Dua baris terakhir hasil eksekusi layak dicermati. Argument 7L bertipe long tidak menemukan overload long, dan long tidak dapat menyempit ke int secara implisit — satu-satunya jalur yang legal adalah melebar ke double, sehingga tercetak double : 7.0. Sebaliknya (byte) 7 lebih cocok melebar ke int (jarak lebih dekat daripada ke double), sehingga overload int yang menang. Conversion pelebaran ini mengikuti aturan yang sama dengan assignment pada Chapter Type Conversion.
Return Type Saja Tidak Cukup #
Signature method hanya memuat nama dan daftar parameter — return type tidak ikut serta. Akibatnya, dua method bernama sama dengan daftar parameter identik akan dianggap deklarasi ganda meski return type-nya berbeda. Mari kita buktikan:
public class OverloadGagal {
static int hitung(int a) {
return a * 2;
}
// Return type berbeda saja, daftar parameter tetap (int)
static long hitung(int a) {
return a * 3L;
}
public static void main(String[] args) {
System.out.println(hitung(5));
}
}Compiler javac menolak dengan keluaran berikut:
OverloadGagal.java:8: error: method hitung(int) is already defined in class OverloadGagal
static long hitung(int a) {
^
1 error
error: compilation failedPesan method hitung(int) is already defined menegaskan bahwa hitung(int) versi int dan versi long adalah method yang sama di mata compiler. Alasannya dapat kita pahami dari sisi pemanggilan: pernyataan hitung(5) pada baris main tidak menyebut return type yang diharapkan, sehingga compiler tidak punya dasar untuk memilih salah satu. Bila return type diizinkan menjadi pembeda, pemanggilan seperti itu menjadi mustahil dijawab — maka bahasa menutup celahnya sejak awal.
Overloading memperkaya cara method menerima masukan. Namun ada perilaku yang lebih dalam dari sekadar pilihan versi: apa yang sebenarnya terjadi pada nilai argument ketika dikirim ke parameter? Apakah method menerima nilai asli, atau salinannya? Jawabannya — Java selalu menyalin nilai — dibuktikan lewat percobaan swap pada Chapter Pass by Value.
Referensi #
- JLS SE25 §8.4.2: Method Signature
- JLS SE25 §15.12.2: Compile-Time Step 2 — Determine Method Signature
- Java API: java.io.PrintStream (overload println)
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
OverloadGagal.java
Unduh berkaspublic class OverloadGagal {
static int hitung(int a) {
return a * 2;
}
// Return type berbeda saja, daftar parameter tetap (int)
static long hitung(int a) {
return a * 3L;
}
public static void main(String[] args) {
System.out.println(hitung(5));
}
}
OverloadSapa.java
Unduh berkaspublic class OverloadSapa {
// Jumlah parameter berbeda
static void sapa() {
System.out.println("Halo!");
}
static void sapa(String nama) {
System.out.println("Halo, " + nama + "!");
}
static void sapa(String nama, String kota) {
System.out.println("Halo, " + nama + " dari " + kota + "!");
}
// Tipe parameter berbeda
static void sapa(int jumlahSiswa) {
System.out.println("Halo kepada " + jumlahSiswa + " siswa!");
}
// Urutan tipe parameter berbeda
static void sapa(String nama, int umur) {
System.out.println("Halo, " + nama + " (" + umur + " tahun)!");
}
static void sapa(int umur, String nama) {
System.out.println("Umur " + umur + " milik " + nama + "!");
}
public static void main(String[] args) {
sapa();
sapa("Budi");
sapa("Budi", "Bandung");
sapa(30);
sapa("Siti", 16);
sapa(17, "Dewi");
}
}
ResolusiTipe.java
Unduh berkaspublic class ResolusiTipe {
static String jenis(int nilai) {
return "int : " + nilai;
}
static String jenis(double nilai) {
return "double : " + nilai;
}
static String jenis(String nilai) {
return "String : " + nilai;
}
public static void main(String[] args) {
System.out.println(jenis(7)); // cocok persis dengan int
System.out.println(jenis(7.0)); // cocok persis dengan double
System.out.println(jenis("7")); // cocok persis dengan String
System.out.println(jenis(7L)); // long melebar ke double
System.out.println(jenis((byte) 7)); // byte melebar ke int
}
}