Konstruktor adalah metode istimewa yang dijalankan tepat ketika objek dibuat, sehingga menjadi tempat alami untuk menyiapkan nilai awal field. Topik ini mengulas konstruktor default yang disediakan kompilator secara diam-diam, konstruktor berparameter yang menerima nilai awal dari pemanggil, beberapa konstruktor sekaligus lewat overloading, serta perantaian konstruktor dengan this(...). Kelas contohnya adalah Titik, titik koordinat dengan field x dan y.
Konstruktor dan aturannya#
Konstruktor dideklarasikan di dalam kelas dengan tiga aturan yang mudah diingat. Namanya sama persis dengan nama kelasnya, deklarasinya tidak menuliskan tipe kembalian, dan tubuhnya berada di antara kurung kurawal seperti metode biasa. Konstruktor boleh memiliki parameter, dan parameter itulah jalur utama untuk mengirim nilai awal dari pemanggil ke objek yang baru lahir.
Eksekusinya melekat pada operator new. Ketika pernyataan new Titik(3, 4) dijalankan, memori untuk objek dialokasikan terlebih dahulu, konstruktor dipanggil dengan argumen 3 dan 4, lalu referensi objek yang sudah terisi itu dikembalikan ke pemanggil. Karena itu, kode di dalam konstruktor adalah kode paling awal yang berjalan atas objek, lebih dulu daripada metode mana pun.
Kesalahan yang paling sering terjadi pada tahap ini adalah menambahkan tipe kembalian pada konstruktor, misalnya void Titik(). Deklarasi semacam itu sah bagi kompilator, tetapi hasilnya bukan konstruktor, melainkan metode biasa yang kebetulan bernama sama dengan kelasnya. Metode itu tidak pernah dipanggil oleh new, sehingga field yang hendak disiapkan tetap bernilai bawaan dan penyiapan nilai awalnya gagal tanpa pesan error apa pun.
Konstruktor default#
Kelas yang tidak mendeklarasikan satu konstruktor pun tetap bisa dibuat objeknya. Kompilator menyisipkan konstruktor default, yaitu konstruktor tanpa parameter dengan tubuh kosong, secara otomatis. Inilah sebabnya kelas yang tidak menulis satu konstruktor pun tetap dapat dibuat dengan new NamaKelas(). Field yang tidak disiapkan pun berhenti pada nilai bawaannya.
// tidak-dijalankan
class Titik {
int x;
int y;
// tidak ada konstruktor yang ditulis,
// sehingga kompilator menyisipkan Titik() dengan tubuh kosong
}Konstruktor default memadai selama objek memang boleh lahir dengan nilai bawaan, misalnya 0 untuk koordinat. Masalah muncul ketika objek wajib lahir dengan nilai tertentu. Titik yang berada di pusat koordinat mungkin boleh lahir di 0, tetapi lingkaran tanpa jari-jari atau rekening tanpa nomor biasanya bermakna tidak lengkap. Untuk kondisi semacam itu, konstruktor perlu ditulis sendiri, dan penulisan itu mengubah satu perilaku halus yang dibahas di bagian berikut.
Konstruktor dengan parameter#
Konstruktor berparameter menerima nilai awal sebagai argumen, lalu mengisinya ke field. Pada contoh berikut, parameter konstruktor bernama sama dengan fieldnya, sehingga kata kunci this dipakai untuk membedakan keduanya. Pembahasan mendalam tentang this menyusul pada topik tersendiri, sementara di sini cukup dibaca sebagai pola baku this.namaField = namaParameter.
public class UjiTitik {
public static void main(String[] args) {
Titik titikA = new Titik(3, 4);
Titik titikB = new Titik(-2, 7);
System.out.println("titikA : x=" + titikA.x + ", y=" + titikA.y);
System.out.println("titikB : x=" + titikB.x + ", y=" + titikB.y);
}
}
class Titik {
int x;
int y;
Titik(int x, int y) {
this.x = x;
this.y = y;
}
}titikA : x=3, y=4
titikB : x=-2, y=7Sekali kelas mendeklarasikan konstruktor sendiri, kompilator berhenti menyisipkan konstruktor default. Perubahan ini sering mengejutkan, karena pemanggilan new Titik() yang sebelumnya sah tiba-tiba gagal dikompilasi.
// tidak-dijalankan
Titik titik = new Titik();
// error: constructor Titik in class Titik cannot be applied to given types
// required: int,int found: no argumentsPesan error di atas adalah perilaku yang diinginkan, bukan penyakit. Objek Titik kini hanya bisa lahir dengan koordinat yang disediakan, sehingga titik tanpa nilai awal tidak mungkin ada. Bila versi tanpa parameter tetap diperlukan, konstruktor tanpa parameter harus dideklarasikan secara eksplisit, dan bagian berikutnya menunjukkan caranya dengan rapi.
Overloading dan rantai this(…)#
Sebuah kelas boleh memiliki beberapa konstruktor sekaligus asalkan daftar parameternya berbeda, kebiasaan yang disebut overloading konstruktor. Pada kelas Titik, tiga cara lahir perlu ditampung, yaitu tanpa koordinat, hanya dengan koordinat x, dan dengan keduanya. Agar ketiganya tidak menyalin kode pengisian field yang sama, konstruktor yang lebih sederhana memanggil konstruktor yang lebih lengkap lewat this(...).
public class UjiTitikOverload {
public static void main(String[] args) {
Titik pusat = new Titik();
Titik diSumbuX = new Titik(5);
Titik bebas = new Titik(3, 4);
System.out.println("pusat : x=" + pusat.x + ", y=" + pusat.y);
System.out.println("diSumbuX : x=" + diSumbuX.x + ", y=" + diSumbuX.y);
System.out.println("bebas : x=" + bebas.x + ", y=" + bebas.y);
}
}
class Titik {
int x;
int y;
Titik() {
this(0, 0);
}
Titik(int x) {
this(x, 0);
}
Titik(int x, int y) {
this.x = x;
this.y = y;
}
}pusat : x=0, y=0
diSumbuX : x=5, y=0
bebas : x=3, y=4Konstruktor yang mengisi field kini hanya satu, sedangkan dua konstruktor lainnya menjadi penerus argumen. Bila logika inisialisasi kelak bertambah, misalnya pencatatan waktu pembuatan, perubahan cukup dilakukan di satu tempat. Perantaian ini hanya sah dengan satu syarat tata bahasa yang ketat.
Kesalahan umum#
- Menuliskan tipe kembalian pada konstruktor, misalnya
void Titik(). Deklarasi itu mengubahnya menjadi metode biasa yang tak pernah dipanggil olehnew, sehingga field tetap bernilai bawaan. Hapus tipe kembalian agar perannya kembali sebagai konstruktor. - Mengandalkan konstruktor default setelah mendeklarasikan konstruktor berparameter. Kompilator sudah berhenti menyisipkannya, sehingga
new Titik()gagal dikompilasi. Deklarasikan konstruktor tanpa parameter secara eksplisit bila cara lahir itu masih diperlukan. - Menempatkan
this(...)bukan sebagai pernyataan pertama. Aturan tata bahasanya mutlak dan kompilasinya langsung gagal. Naikkan pemanggilan itu ke baris pertama, lalu letakkan persiapan lain setelahnya. - Lupa mengisi semua field di dalam konstruktor. Field yang terlewat berhenti pada nilai bawaan tanpa peringatan apa pun. Periksa daftar field ketika menulis atau menyunting konstruktor.
Ringkasan#
- Konstruktor bernama sama dengan kelasnya, tanpa tipe kembalian, dan dijalankan otomatis oleh
newsebelum referensi objek dikembalikan. - Kelas tanpa konstruktor memperoleh konstruktor default tanpa parameter dari kompilator, dan hak itu hilang begitu konstruktor lain ditulis sendiri.
- Beberapa konstruktor dengan daftar parameter berbeda dapat hidup berdampingan, dan
this(...)merantai pemanggilan di antara konstruktor-konstruktor itu. - Pemanggilan
this(...)wajib berada di pernyataan pertama konstruktor.
Referensi#
- Providing Constructors for Your Classes — Oracle — aturan deklarasi konstruktor, overloading, dan perilaku konstruktor default.
- Class and Interface Declarations, JLS 8.8.9 — Oracle — spesifikasi konstruktor default pada Java SE 21.