Java Challengers # 1: Metode Overloading di JVM

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!


pelebaran-tinju-vararg


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.


//   public class Calculator { void calculate(int number1, int number2) { } void calculate(int number1, int number2, int number3) { } } //   public class Calculator { void calculate(int number1, int number2) { } void calculate(double number1, double number2) { } } //   public class Calculator { void calculate(double number1, int number2) { } void calculate(int number1, double number2) { } } 

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


JenisKisaranNilai standarUkuranContoh Literal
booleanbenar atau salahsalah1 bitbenar salah
byte-128 ... 12708 bit1, -90, -128
charKarakter Unicode atau 0 hingga 65 536\ u000016 bit'a', '\ u0031', '\ 201', '\ n', 4
pendek-32.768 ... 32.767016 bit1, 3, 720, 22.000
int-2 147 483 648 ... 2 147 483 647032 bit-2, -1, 0, 1, 9
panjang-9.223.372.036.854.775.808 menjadi 9.223.372.036.854.775.807064 bit-4000L, -900L, 10L, 700L
mengapung3.40282347 x 1038, 1.40239846 x 10-450,032 bit1.67e200f, -1.57e-207f, .9f, 10.4F
dobel1.7976931348623157 x 10308, 4.9406564584124654 x 10-3240,064 bit1.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?


  1. getah
  2. bfce
  3. efce
  4. 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:


  1. Pelebaran
  2. Kemasan (autoboxing dan unboxing)
  3. 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:


Perpanjangan urutan 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) { //      // ,   char, short, byte,  JVM    int calculate(1); } void calculate(short number) {} } 

Aturan yang sama akan berlaku ketika angka 1.0 . Meskipun mungkin float , JVM akan menganggapnya double .


 class Calculator { public static void main(String... args) { //      // ,   float,  JVM    double calculate(1.0); } void calculate(float number) {} } 

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.

Source: https://habr.com/ru/post/id428307/


All Articles