Java Challengers # 1: Metode Overloading di JVM
Hari baik untuk semua
Kami telah meluncurkan aliran berikutnya dari kursus "Pengembang Java" , tetapi kami masih memiliki beberapa materi yang ingin kami bagikan dengan Anda.
Selamat datang di seri artikel Java Challengers ! Seri artikel ini berfokus pada fitur pemrograman Java. Pengembangan mereka adalah cara Anda untuk menjadi programmer Java yang sangat berkualitas.
Menguasai teknik-teknik yang dibahas dalam seri artikel ini membutuhkan beberapa upaya, tetapi mereka akan sangat membantu dalam pengalaman sehari-hari Anda sebagai pengembang java. Menghindari kesalahan lebih mudah ketika Anda tahu cara menerapkan dengan benar teknik pemrograman Java dasar dan kesalahan pelacakan jauh lebih mudah ketika Anda tahu persis apa yang terjadi dalam kode java Anda.
Apakah Anda siap untuk mulai menguasai konsep dasar pemrograman di Jawa? Kalau begitu mari kita mulai dengan puzzle pertama kami!

Istilah "Metode kelebihan"
Tentang istilah overload, pengembang cenderung berpikir bahwa kita berbicara tentang me-reboot sistem, tetapi ini tidak benar. Dalam pemrograman, metode overloading berarti menggunakan nama metode yang sama dengan parameter yang berbeda.
Apa itu kelebihan metode?
Metode overloading adalah teknik pemrograman yang memungkinkan pengembang di kelas yang sama untuk menggunakan nama yang sama untuk metode dengan parameter yang berbeda. Dalam hal ini, kami mengatakan bahwa metode ini kelebihan beban.
Listing 1 menunjukkan metode dengan parameter berbeda yang bervariasi dalam jumlah, jenis, dan urutan.
Daftar 1. Tiga opsi untuk metode kelebihan muatan.
Metode overloading dan tipe primitif
Dalam Listing 1, Anda melihat tipe primitif int
dan double
. Mari kita menyimpang sebentar dan mengingat tipe primitif di Jawa.
Tabel 1. Jenis primitif di Jawa
Jenis | Kisaran | Nilai standar | Ukuran | Contoh Literal |
---|
boolean | benar atau salah | salah | 1 bit | benar salah |
byte | -128 ... 127 | 0 | 8 bit | 1, -90, -128 |
char | Karakter Unicode atau 0 hingga 65 536 | \ u0000 | 16 bit | 'a', '\ u0031', '\ 201', '\ n', 4 |
pendek | -32.768 ... 32.767 | 0 | 16 bit | 1, 3, 720, 22.000 |
int | -2 147 483 648 ... 2 147 483 647 | 0 | 32 bit | -2, -1, 0, 1, 9 |
panjang | -9.223.372.036.854.775.808 menjadi 9.223.372.036.854.775.807 | 0 | 64 bit | -4000L, -900L, 10L, 700L |
mengapung | 3.40282347 x 1038, 1.40239846 x 10-45 | 0,0 | 32 bit | 1.67e200f, -1.57e-207f, .9f, 10.4F |
dobel | 1.7976931348623157 x 10308, 4.9406564584124654 x 10-324 | 0,0 | 64 bit | 1.e700d, -123457e, 37e1d |
Mengapa saya harus menggunakan metode overloading?
Menggunakan overloading membuat kode Anda lebih bersih dan lebih mudah dibaca, dan juga membantu menghindari kesalahan dalam program.
Berbeda dengan Listing 1, bayangkan sebuah program di mana Anda akan memiliki banyak metode calculate()
dengan nama yang mirip dengan calculate1
, calculate2
, calculate3
... tidak bagus, kan? Kelebihan metode calculate()
memungkinkan Anda menggunakan nama yang sama dan hanya mengubah apa yang diperlukan - parameter. Juga sangat mudah untuk menemukan metode kelebihan beban, karena mereka dikelompokkan dalam kode.
Apa kelebihan tidak
Ingatlah bahwa mengubah nama variabel bukanlah kelebihan. Kode berikut tidak dikompilasi:
public class Calculator { void calculate(int firstNumber, int secondNumber){} void calculate(int secondNumber, int thirdNumber){} }
Anda juga tidak bisa membebani metode dengan mengubah nilai balik dalam tanda tangan metode. Kode ini juga tidak mengkompilasi:
public class Calculator { double calculate(int number1, int number2){return 0.0;} long calculate(int number1, int number2){return 0;} }
Konstruktor Kelebihan
Anda dapat membebani konstruktor dengan cara yang sama seperti metode:
public class Calculator { private int number1; private int number2; public Calculator(int number1) { this.number1 = number1; } public Calculator(int number1, int number2) { this.number1 = number1; this.number2 = number2; } }
Memecahkan masalah kelebihan metode
Apakah Anda siap untuk tes pertama? Ayo cari tahu!
Mulailah dengan hati-hati memeriksa kode berikut.
Listing 2. Tantangan metode overloading
public class AdvancedOverloadingChallenge3 { static String x = ""; public static void main(String... doYourBest) { executeAction(1); executeAction(1.0); executeAction(Double.valueOf("5")); executeAction(1L); System.out.println(x); } static void executeAction(int ... var) {x += "a"; } static void executeAction(Integer var) {x += "b"; } static void executeAction(Object var) {x += "c"; } static void executeAction(short var) {x += "d"; } static void executeAction(float var) {x += "e"; } static void executeAction(double var) {x += "f"; } }
Bagus Anda telah mempelajari kodenya. Apa kesimpulannya?
- getah
- bfce
- efce
- aecf
Jawaban yang benar diberikan di akhir artikel.
Apa yang terjadi sekarang? Bagaimana JVM mengkompilasi metode kelebihan beban
Untuk memahami apa yang terjadi pada Listing 2, Anda perlu mengetahui beberapa hal tentang bagaimana JVM mengkompilasi metode overload.
Pertama-tama, JVM cukup malas: itu akan selalu membuat upaya paling sedikit untuk mengeksekusi metode. Jadi, ketika Anda berpikir tentang bagaimana JVM menangani kelebihan beban, perhatikan tiga fitur penting dari kompiler:
- Pelebaran
- Kemasan (autoboxing dan unboxing)
- Argumen Panjang Variabel (vararg)
Jika Anda belum pernah menemukan teknik ini, maka beberapa contoh akan membantu Anda memahaminya. Perhatikan bahwa JVM menjalankannya sesuai dengan urutannya.
Berikut ini contoh ekstensi:
int primitiveIntNumber = 5; double primitiveDoubleNumber = primitiveIntNumber ;
Ini adalah urutan ekstensi dari tipe primitif:

( Catatan penerjemah - Di JLS, ekstensi primitif dijelaskan dengan variasi besar, misalnya, panjang dapat diperluas dalam float atau double. )
Contoh kemasan otomatis:
int primitiveIntNumber = 7; Integer wrapperIntegerNumber = primitiveIntNumber;
Perhatikan apa yang terjadi di balik layar saat menyusun kode:
Integer wrapperIntegerNumber = Integer.valueOf(primitiveIntNumber);
Ini adalah contoh pembongkaran:
Integer wrapperIntegerNumber = 7; int primitiveIntNumber= wrapperIntegerNumber;
Inilah yang terjadi di balik layar ketika menyusun kode ini:
int primitiveIntNumber = wrapperIntegerNumber.intValue();
Dan ini adalah contoh metode dengan argumen panjang variabel. Perhatikan bahwa metode panjang variabel selalu yang terakhir untuk dieksekusi.
execute(int... numbers){}
Apa argumen panjang variabel?
Argumen panjang variabel hanyalah array nilai yang diberikan oleh tiga titik (...). Kami dapat mengirimkan sebanyak bilangan int
ke metode ini.
Sebagai contoh:
execute(1,3,4,6,7,8,8,6,4,6,88...);
Argumen-panjang variabel (varargs) sangat nyaman karena nilai-nilai dapat diteruskan langsung ke suatu metode. Jika kita menggunakan array, kita harus membuat instance array dengan nilai.
Extension: studi kasus
Ketika kami melewati angka 1 langsung ke metode executeAction()
, JVM secara otomatis mengartikannya sebagai int
. Inilah sebabnya mengapa angka ini tidak akan diteruskan ke metode executeAction(short var)
.
Demikian pula, jika kita melewati angka 1.0
JVM akan secara otomatis mengenali bahwa itu adalah dua kali lipat.
Tentu saja, angka 1.0
juga bisa menjadi float
, tetapi jenis literal seperti itu sudah ditentukan sebelumnya. Oleh karena itu, dalam Listing 2, metode executeAction(double var)
.
Saat kami menggunakan pembungkus Double
, ada dua opsi: nomor dapat dibongkar menjadi tipe primitif, atau dapat diperluas ke Object
. (Ingat bahwa setiap kelas di Jawa memperluas kelas Object
.) Dalam hal ini, JVM memilih ekstensi tipe Double
di Object
, karena itu membutuhkan lebih sedikit usaha daripada membongkar.
Yang terakhir kami lewati adalah 1L
dan karena kami menentukan jenisnya, long
.
Kesalahan Kelebihan Umum
Pada saat ini, Anda mungkin mengerti bahwa hal-hal dapat membingungkan dengan metode overloading, jadi mari kita lihat beberapa masalah yang mungkin Anda temui.
Autobox dengan pembungkus
Java adalah bahasa pemrograman yang sangat diketik dan ketika kita menggunakan pembungkus otomatis dengan pembungkus, ada beberapa hal yang perlu kita pertimbangkan. Pertama, kode berikut ini tidak dapat dikompilasi:
int primitiveIntNumber = 7; Double wrapperNumber = primitiveIntNumber;
Autopacking hanya akan bekerja dengan tipe double
karena ketika Anda mengkompilasi kode, itu akan setara dengan ini:
Double number = Double.valueOf(primitiveIntNumber);
Kode ini akan dikompilasi. int
pertama akan diperluas menjadi double
dan kemudian dikemas menjadi Double
. Tetapi dengan pengemasan otomatis, tidak ada ekstensi tipe dan nilai konstruktor Double.valueof
mengharapkan double
, bukan int
. Dalam hal ini, pengemasan otomatis akan berfungsi jika kami membuat konversi tipe eksplisit, misalnya:
Double wrapperNumber = (double) primitiveIntNumber;
Ingatlah bahwa Integer
tidak boleh Long
dan Float
dan tidak bisa Double
. Tidak ada warisan. Masing-masing tipe ini ( Integer
, Long
, Float
, dan Double
) adalah Number
dan Object
.
Jika ragu, ingat saja bahwa nomor pembungkus dapat diperluas ke Number
atau Object
. (Ada banyak lagi yang bisa dikatakan tentang pembungkus, tetapi mari kita tinggalkan untuk artikel lain.)
Kode literal
Ketika kami tidak menentukan tipe angka literal, JVM akan menghitung tipe untuk kami. Jika kita langsung menggunakan angka 1
dalam kode, JVM akan membuatnya sebagai int
. Jika kami mencoba meneruskan 1
langsung ke metode yang menerima short
, maka itu tidak akan dikompilasi.
Sebagai contoh:
class Calculator { public static void main(String... args) {
Aturan yang sama akan berlaku ketika angka 1.0
. Meskipun mungkin float
, JVM akan menganggapnya double
.
class Calculator { public static void main(String... args) {
Kesalahan umum lainnya adalah asumsi bahwa Double
atau pembungkus lainnya lebih baik untuk metode yang mendapat double
.
Faktanya adalah bahwa JVM membutuhkan lebih sedikit upaya untuk memperluas pembungkus Double
menjadi sebuah Object
daripada membukanya menjadi tipe double
primitif.
Untuk meringkas, ketika digunakan langsung dalam kode java, 1
akan menjadi int
dan 1.0
akan menjadi double
. Ekstensi adalah cara termudah untuk mengeksekusi, maka ada pengemasan atau pembongkaran dan operasi terakhir akan selalu menjadi metode dengan panjang variabel.
Seperti fakta yang aneh. Apakah Anda tahu bahwa tipe char
menerima angka?
char anyChar = 127;
Apa yang perlu Anda ingat tentang kelebihan
Overloading adalah teknik yang sangat kuat untuk kasus di mana Anda memerlukan nama metode yang sama dengan parameter yang berbeda. Ini adalah teknik yang berguna karena menggunakan nama yang tepat membuat kode lebih mudah dibaca. Alih-alih menduplikasi nama metode dan menambahkan kekacauan pada kode Anda, Anda bisa membuatnya kelebihan.
Ini menjaga kode tetap bersih dan mudah dibaca, dan juga mengurangi risiko bahwa metode duplikat akan merusak bagian dari sistem.
Apa yang harus diingat: ketika kelebihan metode, JVM akan membuat upaya seminimal mungkin.
Berikut ini urutan jalan paling malas menuju eksekusi:
- Yang pertama adalah pelebaran.
- Yang kedua adalah tinju
- Ketiga, argumen panjang variabel (varargs)
Hal-hal yang perlu dipertimbangkan: situasi sulit muncul ketika mendeklarasikan angka secara langsung: 1
akan int
dan 1.0
akan double
.
Juga ingat bahwa Anda dapat mendeklarasikan tipe ini secara eksplisit menggunakan sintaks 1F
atau 1f
untuk float
dan 1D
atau 1d
untuk double
.
Ini menyimpulkan peran JVM dalam metode overloading. Penting untuk dipahami bahwa JVM secara inheren malas, dan akan selalu mengikuti jalan yang paling malas.
Jawabannya
Jawaban untuk Listing 2 adalah Opsi 3. efce.
Pelajari lebih lanjut tentang kelebihan metode di Jawa
Pengantar kelas dan objek untuk pemula absolut, termasuk bagian kecil tentang metode dan kelebihan metode.
Pelajari lebih lanjut tentang mengapa penting bahwa Java adalah bahasa yang sangat diketik dan belajar tentang tipe primitif Java.
Pelajari batasan dan kelemahan metode kelebihan beban, serta cara mengatasinya dengan menggunakan tipe khusus dan objek parameter.