CodeGym /Java Blog /Acak /Konstruktor Java
John Squirrels
Level 41
San Francisco

Konstruktor Java

Dipublikasikan di grup Acak
Hai! Hari ini kita akan mempertimbangkan topik yang sangat penting yang menyangkut objek kita. Tanpa berlebihan, kami dapat mengatakan bahwa Anda akan menggunakan topik ini dalam kehidupan nyata setiap hari! Kita sedang berbicara tentang Konstruktor Java. Ini mungkin pertama kalinya Anda mendengar istilah ini, tetapi Anda sebenarnya sudah menggunakan konstruktor. Anda hanya tidak menyadarinya :) Kami meyakinkan diri sendiri tentang ini nanti.

Apa sebenarnya konstruktor itu dan mengapa mereka dibutuhkan?

Mari kita pertimbangkan dua contoh.

public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car bugatti = new Car();
       bugatti.model = "Bugatti Veyron";
       bugatti.maxSpeed = 378;

   }
}
Kami menciptakan mobil kami, dan mengatur model dan kecepatan maksimumnya. Tetapi objek Mobil jelas tidak memiliki 2 bidang dalam proyek nyata. Misalnya, mungkin ada 16 bidang!

public class Car {

   String model;// model
   int maxSpeed;// maximum speed
   int wheels;// wheel width
   double engineVolume;// engine volume
   String color;// color
   int productionYear;// production year
   String ownerFirstName;// first name of owner
   String ownerLastName;// last name of owner
   long price;// price
   boolean isNew;// flag indicating whether car is new
   int seatsInTheCar;// number of seats in the car
   String cabinMaterial;// interior material
   boolean insurance;// flag indicating whether car is insured
   String manufacturerCountry;// manufacturer country
   int trunkVolume;// size of the trunk
   int accelerationTo100km;// how long it takes to accelerate to 100 km/h (in seconds)


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.productionYear = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.seatsInTheCar = 2;
       bugatti.maxSpeed = 378;
       bugatti.model = "Bugatti Veyron";

   }

}
Kami telah membuat objek Mobil baru . Ada satu masalah: kami memiliki 16 bidang, tetapi kami hanya menginisialisasi 12 ! Lihat kodenya sekarang dan coba temukan bidang yang kita lupakan! Tidak begitu mudah, ya? Dalam situasi ini, seorang programmer dapat dengan mudah membuat kesalahan dan gagal menginisialisasi beberapa field. Akibatnya, program akan berperilaku salah:

public class Car {

   String model;// model
   int maxSpeed;// maximum speed
   int wheels;// wheel width
   double engineVolume;// engine volume
   String color;// color
   int productionYear;// production year
   String ownerFirstName;// first name of owner
   String ownerLastName;// last name of owner
   long price;// price
   boolean isNew;// flag indicating whether car is new
   int seatsInTheCar;// number of seats in the car
   String cabinMaterial;// interior material
   boolean insurance;// flag indicating whether car is insured
   String manufacturerCountry;// manufacturer country
   int trunkVolume;// size of the trunk
   int accelerationTo100km;// how long it takes to accelerate to 100 km/h (in seconds)


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.productionYear = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.seatsInTheCar = 2;
       bugatti.maxSpeed = 378;
       bugatti.model = "Bugatti Veyron";

       System.out.println("Model: Bugatti Veyron. Engine volume: " + bugatti.engineVolume + ". Trunk volume: " + bugatti.trunkVolume + ". Cabin material: " + bugatti.cabinMaterial +
       ". Wheel width: " + bugatti.wheels + ". Purchased in 2018 by Mr. " + bugatti.ownerLastName);

   }

}
Keluaran konsol: Model: Bugatti Veyron. Volume mesin: 6.3. Volume bagasi: 0. Bahan kabin: nol. Lebar roda: 0. Dibeli pada tahun 2018 oleh Tn. null Pembeli Anda, yang memberikan $2 juta untuk mobil tersebut, jelas tidak suka disebut " Tn. null "! Tapi serius, intinya adalah bahwa program kami salah membuat objek: mobil dengan lebar roda 0 (yaitu tanpa roda sama sekali), bagasi yang hilang, kabin yang terbuat dari bahan yang tidak diketahui, dan yang terpenting, pemilik yang tidak ditentukan . Anda hanya bisa membayangkan bagaimana kesalahan seperti itu bisa "mati" saat program sedang berjalan! Kita perlu menghindari situasi seperti itu. Kami perlu membatasi program kami: saat membuat Mobil baruobjek, kami ingin bidang, seperti model dan kecepatan maksimum, selalu ditentukan. Jika tidak, kami ingin mencegah pembuatan objek. Konstruktor menangani tugas ini dengan mudah. Mereka mendapatkan nama mereka karena suatu alasan. Konstruktor membuat semacam "kerangka" kelas yang harus cocok dengan setiap objek baru. Untuk kenyamanan, mari kembali ke versi yang lebih sederhana dari kelas Mobil dengan dua bidang. Mempertimbangkan persyaratan kami, konstruktor kelas Mobil akan terlihat seperti ini:

public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}

// And creating an object now looks like this:

public static void main(String[] args) {
   Car bugatti = new Car("Bugatti Veyron", 378);
}
Perhatikan bagaimana konstruktor dideklarasikan. Ini mirip dengan metode biasa, tetapi tidak memiliki tipe kembalian. Selain itu, konstruktor menentukan nama kelas ( Car ) yang dimulai dengan huruf besar. Selain itu, konstruktor digunakan dengan kata kunci yang baru untuk Anda: this . Kata kunci ini untuk menunjukkan objek tertentu. Kode di konstruktor

public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
dapat ditafsirkan hampir secara verbatim: " Model untuk mobil ini (yang sedang kita buat sekarang) adalah argumen model yang diteruskan ke konstruktor. MaxSpeed ​​untuk mobil ini (yang sedang kita buat) adalah argumen maxSpeed ​​yang diteruskan ke konstruktor." Dan itulah yang terjadi:

public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car("Bugatti Veyron", 378);
       System.out.println(bugatti.model);
       System.out.println(bugatti.maxSpeed);
   }

}
Keluaran konsol: Bugatti Veyron 378 Konstruktor menetapkan nilai yang diperlukan dengan benar. Anda mungkin telah memperhatikan bahwa konstruktor sangat mirip dengan metode biasa! Begitulah. Konstruktor sebenarnya adalah metode, tetapi dengan fitur khusus :) Sama seperti metode, kami meneruskan argumen ke konstruktor kami. Dan seperti memanggil metode, memanggil konstruktor tidak akan berfungsi kecuali Anda menentukannya:

public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car(); // Error!
   }
  
}
Anda dapat melihat bahwa konstruktor menyelesaikan apa yang ingin kami capai. Sekarang Anda tidak dapat membuat mobil tanpa kecepatan atau model! Kesamaan antara konstruktor dan metode tidak berakhir di sini. Sama seperti metode, konstruktor dapat kelebihan beban. Bayangkan Anda memiliki 2 kucing peliharaan di rumah. Anda mendapatkan salah satunya sebagai anak kucing. Tapi yang kedua Anda ambil dari jalan ketika sudah dewasa, dan Anda tidak tahu persis berapa umurnya. Dalam hal ini, kami ingin program kami dapat membuat dua jenis kucing: yang memiliki nama dan umur (untuk kucing pertama), dan yang hanya memiliki nama (untuk kucing kedua). Untuk ini, kami akan membebani konstruktor:

public class Cat {

   String name;
   int age;

   // For the first cat
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   // For the second cat
   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5);
       Cat streetCatNamedBob = new Cat("Bob");
   }

}
Selain konstruktor asli dengan parameter "nama" dan "usia", kami menambahkan satu lagi hanya dengan parameter nama. Dengan cara yang persis sama seperti kita membebani metode di pelajaran sebelumnya. Sekarang kita bisa membuat kedua jenis kucing :)
Mengapa kita membutuhkan konstruktor?  - 2
Ingat bahwa di awal pelajaran kami mengatakan bahwa Anda telah menggunakan konstruktor tanpa disadari? Kami bersungguh-sungguh dengan apa yang kami katakan. Faktanya adalah bahwa setiap kelas di Jawa memiliki apa yang disebut konstruktor default. Tidak membutuhkan argumen apa pun, tetapi dipanggil setiap kali Anda membuat objek apa pun dari kelas apa pun.

public class Cat {

   public static void main(String[] args) {

       Cat smudge = new Cat(); // The default constructor is invoked here
   }
}
Sekilas memang tidak terlihat. Kami membuat objek, jadi apa? Di mana konstruktor melakukan sesuatu di sini? Untuk melihatnya, mari kita tulis konstruktor kosong untuk kelas Cat secara eksplisit . Kami akan menampilkan beberapa frase di dalamnya. Jika frase ditampilkan, maka konstruktor dipanggil.

public class Cat {

   public Cat() {
       System.out.println("A cat has been created!");
   }

   public static void main(String[] args) {

       Cat smudge = new Cat(); // The default constructor is invoked here
   }
}
Output konsol: Seekor kucing telah dibuat! Ada konfirmasi! Konstruktor default selalu hadir secara tidak terlihat di kelas Anda. Tetapi Anda perlu tahu satu hal lagi tentang itu. Konstruktor default dihilangkan dari kelas setelah Anda membuat konstruktor dengan argumen. Faktanya, kami telah melihat buktinya di atas. Itu ada dalam kode ini:

public class Cat {

   String name;
   int age;

   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat smudge = new Cat(); //Error!
   }
}
Kami tidak dapat membuat Cat tanpa nama dan usia, karena kami mendeklarasikan konstruktor Cat dengan parameter string dan int . Ini menyebabkan konstruktor default segera menghilang dari kelas. Jadi pastikan untuk mengingat bahwa jika Anda memerlukan beberapa konstruktor di kelas Anda, termasuk konstruktor tanpa argumen, Anda harus mendeklarasikannya secara terpisah. Misalnya, kita membuat program untuk klinik hewan. Klinik kami ingin melakukan perbuatan baik dan membantu anak kucing tunawisma yang nama dan usianya tidak diketahui. Maka kode kita akan terlihat seperti ini:

public class Cat {

   String name;
   int age;

   // For cats with owners
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   // For street cats
   public Cat() {
   }

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5);
       Cat streetCat = new Cat();
   }
}
Sekarang setelah kita menulis konstruktor default yang eksplisit, kita dapat membuat kedua jenis kucing :) Seperti halnya metode apa pun, urutan argumen yang diteruskan ke konstruktor sangat penting. Mari kita tukar argumen nama dan usia di konstruktor kita.

public class Cat {

   String name;
   int age;

   public Cat(int age, String name) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 10); // Error!
   }
}
Sebuah kesalahan! Konstruktor dengan jelas menetapkan bahwa saat objek Cat dibuat, objek tersebut harus diberi nomor dan string, dalam urutan ini. Jadi, kode kita tidak berfungsi. Pastikan untuk mengingat ini dan mengingatnya saat mendeklarasikan kelas Anda sendiri:

public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}

public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
Ini adalah dua konstruktor yang sama sekali berbeda! Jika kita mengungkapkan dalam satu kalimat jawaban atas pertanyaan "Mengapa saya membutuhkan konstruktor?", kita mungkin berkata, "Untuk memastikan bahwa objek selalu memiliki status yang valid". Saat Anda menggunakan konstruktor, semua variabel Anda akan diinisialisasi dengan benar. Program Anda tidak akan memiliki mobil dengan kecepatan 0 atau objek "tidak valid" lainnya. Manfaat utama mereka adalah untuk programmer. Jika Anda menginisialisasi bidang secara manual (setelah membuat objek), ada risiko besar bahwa Anda akan melewatkan sesuatu dan menimbulkan bug. Tapi ini tidak akan terjadi dengan konstruktor: jika Anda gagal memberikan semua argumen yang diperlukan atau Anda memberikan jenis argumen yang salah, kompiler akan segera mendaftarkan kesalahan. Kami juga harus mengatakan secara terpisah bahwa Anda tidak boleh meletakkan program Anda' logika di dalam konstruktor. Inilah gunanya metode. Metode adalah tempat Anda harus menentukan semua fungsionalitas yang diperlukan. Mari kita lihat mengapa menambahkan logika ke konstruktor adalah ide yang buruk:

public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factory is called " + this.name);
   System.out.println("It was founded " + this.age + " years ago" );
   System.out.println("Since that time, it has produced " + this.carsCount +  " cars");
   System.out.println("On average, it produces " + (this.carsCount/this.age) + " cars per year");
}

   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Ford", 115 , 50000000);
   }
}
Kami memiliki kelas CarFactory yang menggambarkan pabrik mobil. Di dalam konstruktor, kami menginisialisasi semua bidang dan menyertakan beberapa logika: kami menampilkan beberapa informasi tentang pabrik. Sepertinya tidak ada yang buruk tentang ini. Program bekerja dengan baik. Output konsol: Pabrik mobil kami bernama Ford Didirikan 115 tahun yang lalu Sejak saat itu, telah menghasilkan 5.000.000 mobil Rata-rata, memproduksi 434.782 mobil per tahun Tapi kami sebenarnya telah meletakkan tambang yang tertunda waktu. Dan kode semacam ini dapat dengan mudah menyebabkan kesalahan. Misalkan sekarang kita tidak berbicara tentang Ford, tetapi tentang pabrik baru bernama "Amigo Motors", yang telah berdiri kurang dari setahun dan telah memproduksi 1000 mobil:

public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factor is called " + this.name);
   System.out.println("It was founded " + this.age + " years ago" );
   System.out.println("Since that time, it has produced " + this.carsCount +  " cars");
   System.out.println("On average, it produces " + (this.carsCount/this.age) + " cars per year");
}


   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Amigo Motors", 0 , 1000);
   }
}
Keluaran konsol: Pabrik mobil kami bernama Amigo Motors Exception in thread "main" java.lang.ArithmeticException: / by zero Didirikan 0 tahun yang lalu Sejak saat itu, telah memproduksi 1000 mobil di CarFactory. (CarFactory.java:15) di CarFactory.main(CarFactory.java:23) Proses selesai dengan kode keluar 1 Ledakan! Program diakhiri dengan semacam kesalahan yang tidak dapat dipahami. Coba tebak penyebabnya? Masalahnya ada pada logika yang kita masukkan ke dalam konstruktor. Lebih khusus lagi, baris ini:

System.out.println("On average, it produces " + (this.carsCount/this.age) + " cars per year");
Di sini Anda melakukan perhitungan dan membagi jumlah mobil yang diproduksi dengan umur pabrik. Dan karena pabrik kami masih baru (berusia 0 tahun), kami membaginya dengan 0, yang tidak dapat kami lakukan dalam matematika. Akibatnya, program berakhir dengan kesalahan.

Apa yang seharusnya kami lakukan?

Letakkan semua logika dalam metode terpisah. Sebut saja printFactoryInfo() . Anda bisa meneruskan objek CarFactory sebagai argumen. Anda dapat meletakkan semua logika di sana, dan secara bersamaan menangani potensi kesalahan (seperti kesalahan kami yang melibatkan nol tahun). Untuk masing-masing miliknya. Konstruktor diperlukan untuk menyetel status objek yang valid. Kami memiliki metode untuk logika bisnis. Jangan campur satu dengan yang lain. Untuk memperkuat apa yang Anda pelajari, kami sarankan Anda menonton video pelajaran dari Kursus Java kami
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION