JavaRush /Blog Java /Random-MS /Pembina di Jawa

Pembina di Jawa

Diterbitkan dalam kumpulan
hello! Hari ini kita akan melihat topik yang sangat penting yang berkaitan dengan objek kita. Di sini, tanpa keterlaluan, kami boleh mengatakan bahawa anda akan menggunakan pengetahuan ini setiap hari dalam kerja sebenar! Kami akan bercakap tentang pembina. Anda mungkin mendengar istilah ini buat kali pertama, tetapi sebenarnya anda mungkin pernah menggunakan pembina, tetapi anda sendiri tidak menyedarinya :) Kita akan lihat ini kemudian.

Apakah pembina di Jawa dan mengapa ia diperlukan?

Mari kita lihat 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 = 407;

   }
}
Kami mencipta kereta kami dan menetapkan model dan kelajuan maksimumnya. Walau bagaimanapun, dalam projek sebenar, objek Kereta jelas akan mempunyai lebih daripada 2 medan. Dan, sebagai contoh, 16 medan!
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration 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.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

   }

}
Kami telah mencipta objek Kereta baharu . Satu masalah: kami mempunyai 16 medan, tetapi kami hanya memulakan 12 ! Cuba sekarang gunakan kod untuk mencari kod yang kami terlupa! Tidak begitu mudah, bukan? Dalam keadaan sedemikian, pengaturcara boleh dengan mudah membuat kesilapan dan melangkau permulaan beberapa medan. Akibatnya, tingkah laku program akan menjadi salah:
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration 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.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

       System.out.println("Model Bugatti Veyron. Engine size - " + bugatti.engineVolume + ", trunk - " + bugatti.trunkVolume + ", salon is made of" + bugatti.salonMaterial +
       ", disc width - " + bugatti.wheels + ". Was acquired in 2018 by Mr. " + bugatti.ownerLastName);

   }

}
Output konsol:
Model Bugatti Veyron. Anjakan enjin - 6.3, batang - 0, bahagian dalam diperbuat daripada null, lebar rim - 0. Telah dibeli pada 2018 oleh En. null
Pembeli anda, yang membayar $2 juta untuk sebuah kereta, jelas tidak akan suka dipanggil "Encik Null"! Tetapi serius, pada akhirnya, program kami berakhir dengan objek yang dibuat dengan salah - kereta dengan lebar rim 0 (iaitu, tiada rim sama sekali), batang yang hilang, bahagian dalam yang diperbuat daripada bahan yang tidak diketahui, dan juga milik seseorang yang tidak dikenali. . Seseorang hanya boleh membayangkan bagaimana ralat sedemikian boleh berlaku semasa program sedang berjalan! Kita perlu mengelakkan situasi sedemikian. Kami memerlukan program kami untuk mempunyai had: apabila mencipta objek kenderaan baharu, contohnya, model dan kelajuan maksimum mesti sentiasa ditentukan untuknya. Jika tidak, jangan benarkan penciptaan objek. Fungsi pembina dengan mudah mengatasi tugas ini. Mereka mendapat nama mereka atas sebab tertentu. Pembina mencipta sejenis "rangka" kelas, yang mana setiap objek baharu kelas mesti sepadan. Untuk kemudahan, mari kembali kepada versi yang lebih ringkas bagi kelas Kereta dengan dua medan. Memandangkan keperluan kami, pembina untuk kelas Kereta akan kelihatan seperti ini:
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
Dan mencipta objek kini kelihatan seperti ini:
public static void main(String[] args) {
   Car bugatti = new Car("Bugatti Veyron", 407);
}
Beri perhatianbagaimana pembina dicipta. Ia serupa dengan kaedah biasa, tetapi ia tidak mempunyai jenis pulangan. Dalam kes ini, nama kelas ditunjukkan dalam pembina, juga dengan huruf besar. Dalam kes kami - Kereta . Di samping itu, pembina menggunakan kata kunci baru kepada anda ini . "ini" dalam bahasa Inggeris bermaksud "ini, ini". Perkataan ini merujuk kepada objek tertentu. Kod dalam pembina:
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
boleh diterjemahkan hampir secara literal: " model untuk mesin ini (yang kami cipta sekarang) = hujah model , yang dinyatakan dalam pembina. maxSpeed ​​​​untuk mesin ini (yang kami cipta) = hujah maxSpeed ​​​​, yang dinyatakan dalam pembina." Inilah yang berlaku:
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", 407);
       System.out.println(bugatti.model);
       System.out.println(bugatti.maxSpeed);
   }

}
Output konsol:
Bugatti Veyron 407
Pembina berjaya memberikan nilai yang diperlukan. Anda mungkin perasan bahawa pembina sangat serupa dengan kaedah biasa! Begitulah keadaannya: pembina ialah kaedah, hanya khusus sedikit :) Sama seperti dalam kaedah, kami menghantar parameter kepada pembina kami. Dan sama seperti memanggil kaedah, memanggil pembina tidak akan berfungsi jika anda tidak 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 lihat, pereka telah melakukan apa yang kami cuba capai. Kini anda tidak boleh mencipta kereta tanpa kelajuan atau tanpa model! Persamaan antara pembina dan kaedah tidak berakhir di sana. Sama seperti kaedah, pembina boleh dibebankan. Bayangkan anda mempunyai 2 ekor kucing di rumah. Anda mengambil salah seorang daripada mereka sebagai anak kucing, dan anda membawa yang kedua pulang dari jalan sebagai orang dewasa dan anda tidak tahu berapa umurnya. Ini bermakna program kami sepatutnya dapat mencipta dua jenis kucing - dengan nama dan umur untuk kucing pertama, dan hanya dengan nama - untuk kucing kedua. Untuk melakukan ini, kami akan membebankan pembina:
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 barsik = new Cat("Barsik", 5);
       Cat streetCatNamedBob = new Cat("Bob");
   }

}
Kepada pembina asal dengan parameter "nama" dan "umur" kami menambah satu lagi, hanya dengan nama. Kami membebankan kaedah dengan cara yang sama dalam pelajaran sebelumnya. Kini kami berjaya mencipta kedua-dua versi kucing :) Mengapa pembina diperlukan?  - 2Adakah anda masih ingat pada permulaan kuliah kami mengatakan bahawa anda telah menggunakan pembina, tetapi anda tidak menyedarinya? Ini adalah benar. Hakikatnya ialah setiap kelas di Java mempunyai apa yang dipanggil pembina lalai. Ia tidak mempunyai sebarang hujah, tetapi ia menyala setiap kali sebarang objek dari mana-mana kelas dicipta.
public class Cat {

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
Pada pandangan pertama ini tidak ketara. Nah, kami mencipta objek dan menciptanya, di manakah kerja pereka bentuk? Untuk melihat ini, mari kita tulis pembina kosong untuk kelas Cat dengan tangan kita sendiri , dan di dalamnya kita akan mencetak beberapa frasa ke konsol. Jika ia dipaparkan, maka pembina telah berfungsi.
public class Cat {

   public Cat() {
       System.out.println("Created a cat!");
   }

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
Output konsol:
Mereka mencipta kucing!
Ini pengesahannya! Pembina lalai sentiasa tidak kelihatan dalam kelas anda. Tetapi anda perlu mengetahui satu lagi cirinya. Pembina lalai hilang daripada kelas apabila anda mencipta beberapa pembina dengan hujah. Buktinya, sebenarnya, kita sudah lihat di atas. Di sini dalam kod 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 barsik = new Cat(); //error!
   }
}
Kami tidak boleh mencipta kucing tanpa nama dan umur kerana kami menentukan pembina untuk Cat : string + number. Pembina lalai hilang dari kelas sejurus selepas ini. Oleh itu, pastikan anda ingat: jika anda memerlukan beberapa pembina dalam kelas anda, termasuk yang kosong, anda perlu menciptanya secara berasingan. Sebagai contoh, kami sedang membuat program untuk klinik veterinar. Klinik kami ingin melakukan perbuatan baik dan membantu kucing gelandangan, yang kami tidak tahu nama atau umur mereka. Kemudian kod kami sepatutnya kelihatan seperti ini:
public class Cat {

   String name;
   int age;

   //for domestic cats
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   //for street cats
   public Cat() {
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5);
       Cat streetCat = new Cat();
   }
}
Sekarang kita telah menulis pembina lalai secara eksplisit, kita boleh mencipta kucing daripada kedua-dua jenis :) Untuk pembina (seperti mana-mana kaedah), susunan hujah adalah sangat penting. Mari kita tukar nama dan hujah umur dalam pembina kami.
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 barsik = new Cat("Barsik", 10); //error!
   }
}
Ralat! Pembina dengan jelas menyatakan bahawa apabila objek Cat dicipta, ia mesti diluluskan nombor dan rentetan, dalam susunan itu. Itulah sebabnya kod kami tidak berfungsi. Pastikan anda mengingati perkara ini dan ingat perkara ini semasa membuat 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 pereka yang sama sekali berbeza! Jika kita menyatakan jawapan kepada soalan "Mengapa kita memerlukan pembina?" Dalam satu ayat, kita boleh mengatakan: supaya objek sentiasa dalam keadaan yang betul. Apabila anda menggunakan pembina, semua pembolehubah anda akan dimulakan dengan betul, dan tidak akan ada kereta dengan kelajuan 0 atau objek "salah" lain dalam program ini. Penggunaan mereka sangat bermanfaat, pertama sekali, untuk pengaturcara itu sendiri. Jika anda memulakan medan sendiri, terdapat risiko tinggi kehilangan sesuatu dan membuat kesilapan. Tetapi ini tidak akan berlaku dengan pembina: jika anda tidak menyerahkan semua hujah yang diperlukan kepadanya atau mencampurkan jenisnya, pengkompil akan segera membuang ralat. Perlu dinyatakan secara berasingan bahawa anda tidak sepatutnya meletakkan logik program anda di dalam pembina. Untuk melakukan ini, anda mempunyai kaedah yang boleh digunakan di mana anda boleh menerangkan semua fungsi yang anda perlukan. Mari kita lihat mengapa logik pembina adalah idea yang tidak baik:
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("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}

   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Ford", 115 , 50000000);
   }
}
Kami mempunyai kelas CarFactory yang menerangkan kilang untuk mengeluarkan kereta. Di dalam pembina, kami memulakan semua medan dan meletakkan logik di sini: kami memaparkan beberapa maklumat tentang kilang ke konsol. Nampaknya tidak ada yang salah dengan ini, program ini berfungsi dengan sempurna. Output konsol:
Kilang kereta kami dipanggil Ford. Ia diasaskan 115 tahun yang lalu. Pada masa ini, ia telah mengeluarkan 50,000,000 kereta. Secara purata, ia mengeluarkan 434,782 kereta setahun.
Tetapi sebenarnya, kita telah menanam bom jangka. Dan kod sedemikian boleh membawa kepada ralat dengan mudah. Bayangkan sekarang kita tidak bercakap tentang Ford, tetapi mengenai kilang baru "Amigo Motors", yang telah wujud kurang dari setahun dan telah menghasilkan 1000 kereta:
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("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}


   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Amigo Motors", 0 , 1000);
   }
}
Output konsol:
Kilang kereta kami dipanggil Amigo Motors Exception dalam benang "utama" java.lang.ArithmeticException: / by zero Ia diasaskan 0 tahun yang lalu Pada masa ini, ia menghasilkan 1000 kereta di CarFactory.<init>(CarFactory.java:15) di CarFactory.main(CarFactory.java:23) Proses selesai dengan kod keluar 1</init>
Kami telah tiba! Program ini berakhir dengan beberapa ralat pelik. Cuba teka apa sebabnya? Sebabnya ialah logik yang kami letakkan dalam pembina. Secara khusus, dalam baris ini:
System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
Di sini kami membuat pengiraan dan membahagikan bilangan kereta yang dihasilkan mengikut umur kilang. Dan kerana kilang kami baru (iaitu, ia berusia 0 tahun), hasilnya adalah pembahagian dengan 0, yang dilarang dalam matematik. Akibatnya, program ditamatkan dengan ralat. Apa yang sepatutnya kita lakukan? Alihkan semua logik ke dalam kaedah yang berasingan dan panggilnya, sebagai contoh, printFactoryInfo() . Anda boleh memberikannya objek CarFactory sebagai parameter . Anda juga boleh meletakkan semua logik di sana, dan pada masa yang sama - memproses kemungkinan ralat, seperti kami dengan sifar tahun. Kepada masing-masing miliknya. Pembina diperlukan untuk menetapkan keadaan objek dengan betul. Untuk logik perniagaan kami mempunyai kaedah. Anda tidak sepatutnya mencampurkan satu dengan yang lain.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION