Panduan untuk Konstruktor di Java

1. Perkenalan

Konstruktor adalah penjaga gerbang desain berorientasi objek .

Dalam tutorial ini, kita akan melihat bagaimana mereka bertindak sebagai satu lokasi untuk menginisialisasi keadaan internal objek yang sedang dibuat.

Mari terus maju dan buat objek sederhana yang mewakili rekening bank.

2. Menyiapkan Rekening Bank

Bayangkan kita perlu membuat kelas yang mewakili rekening bank. Ini akan berisi Nama, Tanggal Pembuatan dan Saldo.

Juga, mari kita ganti metode toString untuk mencetak detail ke konsol:

class BankAccount { String name; LocalDateTime opened; double balance; @Override public String toString() { return String.format("%s, %s, %f", this.name, this.opened.toString(), this.balance); } } 

Sekarang, kelas ini berisi semua bidang yang diperlukan untuk menyimpan informasi tentang rekening bank, tetapi belum berisi konstruktor.

Ini berarti jika kita membuat objek baru, nilai bidang tidak akan diinisialisasi:

BankAccount account = new BankAccount(); account.toString(); 

Menjalankan metode toString di atas akan menghasilkan pengecualian karena nama objek dan dibuka masih null :

java.lang.NullPointerException at com.baeldung.constructors.BankAccount.toString(BankAccount.java:12) at com.baeldung.constructors.ConstructorUnitTest .givenNoExplicitContructor_whenUsed_thenFails(ConstructorUnitTest.java:23) 

3. Pembuat Tanpa Argumen

Mari perbaiki itu dengan konstruktor:

class BankAccount { public BankAccount() { this.name = ""; this.opened = LocalDateTime.now(); this.balance = 0.0d; } } 

Perhatikan beberapa hal tentang konstruktor yang baru saja kita tulis. Pertama, ini adalah metode, tetapi tidak memiliki tipe pengembalian. Itu karena konstruktor secara implisit mengembalikan tipe objek yang dibuatnya. Memanggil BankAccount () baru sekarang akan memanggil konstruktor di atas.

Kedua, tidak membutuhkan argumen. Jenis konstruktor khusus ini disebut konstruktor o-argumen .

Mengapa kita tidak membutuhkannya untuk pertama kali? Itu karena ketika kita tidak secara eksplisit menulis konstruktor apa pun, kompilator menambahkan konstruktor default tanpa argumen .

Inilah mengapa kami dapat membuat objek untuk pertama kalinya, meskipun kami tidak menulis konstruktor secara eksplisit. Defaultnya, tidak ada konstruktor argumen hanya akan mengatur semua anggota ke nilai defaultnya.

Untuk objek, nilainya null, yang menghasilkan pengecualian yang kita lihat sebelumnya.

4. Sebuah Pembuat Parameter

Sekarang, manfaat nyata dari konstruktor adalah mereka membantu kita mempertahankan enkapsulasi saat memasukkan status ke dalam objek.

Jadi, untuk melakukan sesuatu yang sangat berguna dengan rekening bank ini, kita harus benar-benar dapat memasukkan beberapa nilai awal ke dalam objek.

Untuk melakukan itu, mari kita tulis konstruktor berparameter , yaitu konstruktor yang membutuhkan beberapa argumen :

class BankAccount { public BankAccount() { ... } public BankAccount(String name, LocalDateTime opened, double balance) { this.name = name; this.opened = opened; this.balance = balance; } } 

Sekarang kita dapat melakukan sesuatu yang berguna dengan kelas BankAccount kita :

 LocalDateTime opened = LocalDateTime.of(2018, Month.JUNE, 29, 06, 30, 00); BankAccount account = new BankAccount("Tom", opened, 1000.0f); account.toString(); 

Perhatikan, bahwa kelas kita sekarang memiliki 2 konstruktor. Konstruktor argumen dan eksplisit tanpa parameter dan konstruktor berparameter.

Kita dapat membuat konstruktor sebanyak yang kita suka, tetapi mungkin kita tidak ingin membuat terlalu banyak. Ini akan sedikit membingungkan.

Jika kami menemukan terlalu banyak konstruktor dalam kode kami, beberapa Pola Desain Kreasi mungkin bisa membantu.

5. Pembuat Salinan

Konstruktor tidak perlu dibatasi pada inisialisasi saja. Mereka juga bisa digunakan untuk menciptakan perilaku. Bayangkan bahwa kita harus dapat membuat akun baru dari yang sudah ada.

Akun baru harus memiliki nama yang sama dengan akun lama, tanggal pembuatan hari ini, dan tidak ada dana. Kita dapat melakukannya menggunakan konstruktor salinan :

public BankAccount(BankAccount other) { this.name = other.name; this.opened = LocalDateTime.now(); this.balance = 0.0f; } 

Sekarang kami memiliki perilaku berikut:

LocalDateTime opened = LocalDateTime.of(2018, Month.JUNE, 29, 06, 30, 00); BankAccount account = new BankAccount("Tim", opened, 1000.0f); BankAccount newAccount = new BankAccount(account); assertThat(account.getName()).isEqualTo(newAccount.getName()); assertThat(account.getOpened()).isNotEqualTo(newAccount.getOpened()); assertThat(newAccount.getBalance()).isEqualTo(0.0f); 

6. Seorang Pembuat Dirantai

Tentu saja, kita mungkin dapat menyimpulkan beberapa parameter konstruktor atau memberikan beberapa di antaranya nilai default.

Misalnya, kita bisa membuat rekening bank baru hanya dengan namanya.

Jadi, mari buat konstruktor dengan parameter nama dan berikan nilai default parameter lainnya:

public BankAccount(String name, LocalDateTime opened, double balance) { this.name = name; this.opened = opened; this.balance = balance; } public BankAccount(String name) { this(name, LocalDateTime.now(), 0.0f); }

Dengan kata kunci ini, kami memanggil konstruktor lainnya.

Kita harus ingat bahwa jika kita ingin merantai konstruktor superclass kita harus menggunakan super daripada ini .

Juga, ingatlah bahwa ekspresi ini atau super harus selalu menjadi pernyataan pertama.

7. Jenis Nilai

Penggunaan konstruktor di Java yang menarik adalah dalam pembuatan Value Objects . Objek nilai adalah objek yang tidak mengubah keadaan internalnya setelah inisialisasi.

Artinya, objek itu tidak bisa diubah . Keabadian di Jawa sedikit berbeda dan harus berhati-hati saat membuat objek.

Mari lanjutkan dan buat kelas yang tidak dapat diubah:

class Transaction { final BankAccount bankAccount; final LocalDateTime date; final double amount; public Transaction(BankAccount account, LocalDateTime date, double amount) { this.bankAccount = account; this.date = date; this.amount = amount; } } 

Perhatikan, kita sekarang menggunakan kata kunci terakhir saat mendefinisikan anggota kelas. Ini berarti bahwa setiap anggota hanya dapat diinisialisasi dalam konstruktor kelas. Mereka tidak dapat dipindahkan nanti di dalam metode lain. Kita bisa membaca nilai-nilai itu, tapi tidak bisa mengubahnya.

Jika kita membuat beberapa konstruktor untuk kelas Transaction , setiap konstruktor perlu menginisialisasi setiap variabel terakhir. Tidak melakukannya akan mengakibatkan kesalahan kompilasi.

8. Kesimpulan

Kami telah melakukan tur melalui berbagai cara di mana konstruktor membangun objek. Ketika digunakan dengan bijaksana, konstruksi membentuk blok bangunan dasar dari desain Berorientasi Objek di Java.

Seperti biasa, contoh kode dapat ditemukan di GitHub.