Di balik setiap kelas Java, termasuk kelas yang ditulis sendiri, terdapat satu leluhur yang sama, yaitu kelas java.lang.Object. Setiap kelas mewarisinya secara implisit tanpa perlu pernyataan apa pun, sehingga perilaku dasar seperti mencetak diri dan membandingkan diri tersedia sejak objek pertama dibuat. Topik ini mengenal Object sebagai wadah universal untuk objek apa pun, mengurai pola toString bawaan, dan membuktikan bahwa equals bawaan membandingkan referensi, bukan isi.
Object sebagai leluhur semua kelas#
Kelas yang tidak menuliskan extends tetap mewarisi Object, dan sebab itulah metode seperti toString(), equals(), dan getClass() bisa dipanggil atas objek apa pun tanpa mendeklarasikannya. Konsekuensi lain bersifat praktis, yaitu variabel bertipe Object dapat menampung referensi menuju objek dari kelas mana pun. Wadah universal seperti ini dipakai luas di perpustakaan standar pada masa sebelum generics berkembang.
public class UjiObject {
public static void main(String[] args) {
Object wadah = new Buku("Peta Jalur Pendakian", 240);
System.out.println("Tipe asli : " + wadah.getClass().getSimpleName());
Buku buku = (Buku) wadah;
System.out.println("Judul : " + buku.judul);
String teksDefault = String.valueOf(wadah);
System.out.println("Pola toString default (diawali Buku@) : " + teksDefault.startsWith("Buku@"));
}
}
class Buku {
String judul;
int jumlahHalaman;
Buku(String judul, int jumlahHalaman) {
this.judul = judul;
this.jumlahHalaman = jumlahHalaman;
}
}Tipe asli : Buku
Judul : Peta Jalur Pendakian
Pola toString default (diawali Buku@) : trueVariabel wadah bertipe Object, tetapi isinya tetap objek Buku, dan metode getClass() yang diwarisi dari Object membuktikannya dengan mengembalikan informasi tipe aslinya. Karena kompilator hanya melihat tipe variabel, penggunaan kembali objek tersebut sebagai Buku menuntut casting, yaitu penulisan (Buku) secara eksplisit sebelum anggota khusus Buku dapat diakses. Baris terakhir memeriksa teks hasil toString bawaan, dan pola yang ditemukannya diuraikan berikut ini.
toString dan pola bawaannya#
Metode toString bawaan menyusun teks dari nama kelas, tanda @, dan angka heksadesimal yang berasal dari hash code identitas objek, sehingga bentuknya seperti Buku@1b6d3586. Angka heksadesimal itu berbeda pada setiap eksekusi karena berasal dari alamat identitas objek, bukan dari isinya. Justru karena itulah program di atas hanya memeriksa pola awalnya lewat startsWith alih-alih mencetak teks lengkapnya ke keluaran.
Representasi bawaan ini jarang dikehendaki dalam laporan maupun log, sehingga kelas biasanya menyediakan toString sendiri dengan teks yang bermakna dan stabil. Kelas Buku pada program berikut menimpa metode tersebut dengan menyusun isi fieldnya ke dalam satu baris, dan pemanggilan println(buku) otomatis memakai versi yang baru.
public class UjiToString {
public static void main(String[] args) {
Buku buku = new Buku("Peta Jalur Pendakian", 240);
System.out.println(buku);
}
}
class Buku {
String judul;
int jumlahHalaman;
Buku(String judul, int jumlahHalaman) {
this.judul = judul;
this.jumlahHalaman = jumlahHalaman;
}
public String toString() {
return "Buku{judul=" + judul + ", halaman=" + jumlahHalaman + "}";
}
}Buku{judul=Peta Jalur Pendakian, halaman=240}Keluaran kini dapat direproduksi berulang kali karena teksnya hanya menyusun field, tanpa bagian yang berubah-ubah. Kebiasaan menyediakan toString yang informatif membantu saat debugging, karena objek yang dicetak langsung memperlihatkan isinya, bukan nama kelas dengan angka yang tidak berhubungan dengan data apa pun.
equals bawaan membandingkan referensi#
Metode equals bawaan didefinisikan sama persis dengan operator ==, yaitu bernilai true hanya ketika kedua sisi menunjuk objek yang sama. Dua objek dengan isi field yang identik tetap dianggap berbeda karena keduanya lahir dari pemanggilan new yang terpisah. Program berikut mengukur perilaku itu langsung.
public class UjiEquals {
public static void main(String[] args) {
Buku bukuA = new Buku("Peta Jalur Pendakian", 240);
Buku bukuB = new Buku("Peta Jalur Pendakian", 240);
Buku bukuC = bukuA;
System.out.println("bukuA.equals(bukuB) : " + bukuA.equals(bukuB));
System.out.println("bukuA.equals(bukuC) : " + bukuA.equals(bukuC));
}
}
class Buku {
String judul;
int jumlahHalaman;
Buku(String judul, int jumlahHalaman) {
this.judul = judul;
this.jumlahHalaman = jumlahHalaman;
}
}bukuA.equals(bukuB) : false
bukuA.equals(bukuC) : truePercobaan pertama menghasilkan false karena bukuA dan bukuB menunjuk dua objek berbeda, sedangkan percobaan kedua menghasilkan true karena bukuC hanyalah salinan referensi dari bukuA. Isi field sama sekali tidak terlibat dalam kedua pembandingan tersebut. Bila kesetaraan isi yang dikehendaki, metode equals harus ditulis ulang agar membandingkan field yang relevan, pekerjaan yang diatur oleh kontrak resmi dalam spesifikasi bahasa dan wajib disertai penyesuaian hashCode. Untuk pembawa data, kelas record memberikan versi siap pakai dari perbandingan semacam itu.
Kesalahan umum#
- Memakai
==atauequalsbawaan untuk membandingkan isi dua objek. Keduanya membandingkan referensi, sehingga hasilnyafalseuntuk dua objek berbeda walau fieldnya identik. Tulis ulangequalsatau gunakan kelas yang sudah menyediakannya. - Mengharapkan
toStringbawaan menampilkan isi objek. Teksnya berisi nama kelas dengan hash code identitas yang berubah setiap eksekusi. SediakantoStringsendiri bila teksnya akan dibaca manusia. - Mencetak hasil
toStringbawaan lalu menggunakannya sebagai penanda di log. Nilainya tidak stabil antarjalankan, sehingga pencocokan log menjadi menyesatkan. Log yang stabil memerlukan representasi yang menyertakan isi, bukan identitas. - Melakukan casting dari
Objecttanpa memastikan tipenya. Pemanggilan(Buku) wadahatas objek yang bukan Buku memunculkanClassCastExceptionsaat program berjalan. Periksa denganinstanceofterlebih dahulu bila tipenya tidak pasti.
Ringkasan#
- Object adalah leluhur semua kelas Java, diwarisi secara implisit, dan menjadi sumber metode dasar seperti
toString,equals, dangetClass. - Variabel bertipe
Objectdapat menampung objek apa pun, dengan pembayaran berupa casting kembali ke tipe asli sebelum anggota khususnya dapat dipakai. toStringbawaan menghasilkan nama kelas,@, dan hash code identitas, sehingga kelas biasanya menyediakan versi sendiri yang stabil dan informatif.equalsbawaan setara dengan==, yaitu membandingkan referensi, sedangkan perbandingan isi menuntut penulisan ulang yang mengikuti kontrak besertahashCode.
Referensi#
- Object as a Superclass — Oracle
— penjelasan metode yang diwariskan Object, termasuk
toStringdanequals. - Object (Java SE 21 API Specification) — Oracle — kontrak lengkap metode-metode kelas Object.