Kelas dan Objek

Merancang kelas pertama dengan field dan metode, membuat objek dengan new, dan memahami referensi.

Daftar isi

Setiap program Java berukuran sedang ke atas dibangun dari kelas, yaitu unit yang menggabungkan data dan perilaku dalam satu wadah. Topik ini memandu perancangan kelas pertama lengkap dengan field, yakni variabel yang melekat pada objek, beserta metode yang mengolah data itu. Objek dibuat lewat operator new, dan makna referensi (reference) sebagai “alamat” menuju objek ditelusuri lewat contoh yang bisa dijalankan. Kelas contoh yang dipakai adalah Buku, penyimpan judul dan jumlah halaman.

Merancang kelas pertama#

Kelas dideklarasikan dengan kata kunci class diikuti nama kelasnya, kemudian tubuh kelas berada di antara kurung kurawal. Di dalam tubuh kelas terdapat dua jenis anggota yang paling sering dipakai. Field adalah variabel yang dimiliki setiap objek, sedangkan metode adalah perilaku yang bisa dipanggil atas objek tersebut. Kerangka kelas Buku berikut memuat dua field dan satu metode.

java Contoh: kerangka kelas Buku
// tidak-dijalankan
class Buku {
    String judul;
    int jumlahHalaman;

    void tampilkanInfo() {
        System.out.println(judul + " (" + jumlahHalaman + " halaman)");
    }
}

Field judul bertipe String dan field jumlahHalaman bertipe int sama-sama belum diberi nilai, sedangkan metode tampilkanInfo() dideklarasikan tanpa parameter dan tanpa nilai kembalian karena tugasnya hanya mencetak. Perhatikan bahwa di dalam metode, field dipakai tanpa awalan apa pun. Java menganggap judul sebagai field milik objek yang sedang diproses, bukan variabel lokal metode.

Nama kelas mengikuti kebiasaan yang berlaku luas, yaitu diawali huruf kapital untuk setiap kata (PascalCase), sedangkan nama field dan metode diawali huruf kecil (camelCase). Pada contoh yang memuat lebih dari satu kelas dalam satu berkas, hanya satu kelas yang diberi kata kunci public, dan kelas itulah yang namanya sama dengan nama berkasnya. Kelas Buku pada contoh di atas sengaja ditulis tanpa public karena posisi kelas utama pemilik metode main sudah dipegang kelas lain di berkas yang sama.

Membuat objek dengan new#

Kelas hanya cetak biru, sehingga deklarasinya saja belum menghasilkan apa pun di memori. Operator new menciptakan objek baru di heap, yaitu area memori tempat objek hidup, menjalankan konstruktornya, lalu mengembalikan referensi menuju objek tersebut. Referensi itu ditampung dalam variabel bertipe kelasnya. Program berikut memuat kelas Buku sekaligus kelas utama yang membuat dua objek darinya.

java UjiBuku.java
public class UjiBuku {

    public static void main(String[] args) {
        Buku bukuA = new Buku();
        bukuA.judul = "Panduan Merawat Sepeda";
        bukuA.jumlahHalaman = 180;
        Buku bukuB = new Buku();
        bukuB.judul = "Peta Jalur Pendakian";
        bukuB.jumlahHalaman = 240;
        bukuA.tampilkanInfo();
        bukuB.tampilkanInfo();
    }
}

class Buku {
    String judul;
    int jumlahHalaman;

    void tampilkanInfo() {
        System.out.println(judul + " (" + jumlahHalaman + " halaman)");
    }
}
text Keluaran
Panduan Merawat Sepeda (180 halaman)
Peta Jalur Pendakian (240 halaman)

Menjalankan programnya dari terminal cukup dengan satu perintah berikut.

bash
# berada di folder tempat UjiBuku.java disimpan
java UjiBuku.java
text Keluaran
Panduan Merawat Sepeda (180 halaman)
Peta Jalur Pendakian (240 halaman)

Notasi titik pada bukuA.judul berarti mengakses anggota milik objek yang dirujuk bukuA. Setiap pemanggilan new Buku() menghasilkan objek yang berdiri sendiri dengan salinan fieldnya masing-masing, sehingga mengubah bukuA.jumlahHalaman tidak menyentuh bukuB. Hubungan kelas sebagai cetakan dan objek sebagai wujudnya digambarkan berikut ini.

kelas Bukujudul : StringjumlahHalaman : inttampilkanInfo()cetakan, belum wujud di memorinewnewobjek bukuAjudul = "Panduan Merawat Sepeda"jumlahHalaman = 180objek bukuBjudul = "Peta Jalur Pendakian"jumlahHalaman = 240
Kelas Buku sebagai cetakan dan dua objek hasil pembuatannya

Referensi objek#

Variabel bertipe kelas tidak menyimpan objeknya, melainkan referensi menuju objek itu di heap. Konsekuensinya terasa saat satu referensi disalin ke variabel lain. Penugasan Buku bukuC = bukuA tidak menduplikasi objek, tetapi menyalin alamatnya, sehingga bukuC dan bukuA menunjuk objek yang sama. Perubahan lewat salah satu variabel pun terlihat oleh variabel yang lain. Operator == pada tipe objek juga membandingkan referensi, bukan isi field.

java UjiReferensiBuku.java
public class UjiReferensiBuku {

    public static void main(String[] args) {
        Buku bukuA = new Buku();
        bukuA.judul = "Peta Jalur Pendakian";
        bukuA.jumlahHalaman = 240;
        Buku bukuB = new Buku();
        bukuB.judul = "Panduan Merawat Sepeda";
        bukuB.jumlahHalaman = 180;

        System.out.println("bukuA == bukuB : " + (bukuA == bukuB));

        Buku bukuC = bukuA;
        bukuC.jumlahHalaman = 260;
        System.out.println("Halaman bukuA : " + bukuA.jumlahHalaman);
        System.out.println("Halaman bukuC : " + bukuC.jumlahHalaman);
        System.out.println("bukuA == bukuC : " + (bukuA == bukuC));
    }
}

class Buku {
    String judul;
    int jumlahHalaman;

    void tampilkanInfo() {
        System.out.println(judul + " (" + jumlahHalaman + " halaman)");
    }
}
text Keluaran
bukuA == bukuB : false
Halaman bukuA : 260
Halaman bukuC : 260
bukuA == bukuC : true

Hasilnya menegaskan dua hal sekaligus. Pembandingan bukuA == bukuB bernilai false karena new yang kedua menciptakan objek lain, kendati fieldnya mirip. Sebaliknya, perubahan bukuC.jumlahHalaman ikut mengubah data yang dibaca lewat bukuA karena keduanya memegang referensi yang sama. Bila duplikasi objek memang dikehendaki, objek baru harus dibuat secara eksplisit dan fieldnya disalin satu per satu.

Kesalahan umum#

  • Mengira penugasan antarvariabel menyalin objek. Yang disalin hanya referensinya, sehingga dua variabel mengubah objek yang sama. Buat objek baru dengan new, lalu salin fieldnya satu per satu bila duplikasi diperlukan.
  • Memanggil metode lewat variabel yang belum diberi objek. Variabel semacam itu bernilai null, dan pemakaiannya memunculkan NullPointerException saat program berjalan. Pastikan new sudah dieksekusi sebelum variabel dipakai.
  • Menamai berkas berbeda dari kelas public di dalamnya. Kompilator javac menuntut kesamaan nama, dan kompilasi gagal sebelum program sempat dijalankan. Samakan nama berkas dengan kelas public-nya.
  • Menganggap dua objek berisi nilai sama berarti objek yang sama. Pembandingan == bekerja pada referensi, sehingga hasilnya false untuk dua objek terpisah walau isinya identik.

Ringkasan#

  • Kelas menggabungkan field sebagai data dan metode sebagai perilaku, sedangkan objek adalah wujud nyata kelas yang dibuat dengan new dan hidup di heap.
  • Setiap new menghasilkan objek terpisah dengan salinan fieldnya sendiri.
  • Variabel bertipe kelas menyimpan referensi, sehingga penugasan antarvariabel menyalin alamat, bukan isi objek.
  • Operator == pada objek membandingkan referensi, bukan nilai field.

Referensi#