Kata kunci this muncul di hampir semua constructor Java yang kita temui, termasuk pada contoh-contoh Chapter sebelumnya, dan kini saatnya membuka kotaknya. Setiap kali method instance atau constructor berjalan, kode tersebut selalu berjalan “di atas” satu object tertentu — object yang menjadi pemanggil method, atau object yang sedang diciptakan new. Kata kunci this adalah referensi menuju object tersebut; this ibarat kartu identitas yang JVM sertakan secara otomatis ke setiap method instance. Pada Chapter ini kita bedah tiga wajah this: sebagai pembeda field dari parameter, sebagai panggilan delegasi constructor this(...), dan sebagai argumen yang mengirim object aktif ke method lain.

this Menunjuk Object Aktif #

Mari kita mulai dari mekanisme dasarnya. Ketika program menjalankan bukuA.catatKeRak(rak), JVM tidak hanya membawa argumen rak — JVM juga membawa referensi tersembunyi ke bukuA. Referensi tersembunyi itulah yang bernama this di dalam badan method. Dua pemanggilan berbeda, bukuA.catatKeRak(...) dan bukuB.catatKeRak(...), menjalankan baris-baris method yang sama, tetapi dengan this yang berbeda: yang pertama menunjuk object bukuA, yang kedua menunjuk object bukuB.

Konsekuensi pentingnya: this hanya ada di dalam konteks instance. Method static — termasuk main — tidak melekat pada object tertentu, sehingga this tidak bisa dipakai di sana. Compiler menolak kode seperti System.out.println(this) di dalam main dengan pesan non-static variable this cannot be referenced from a static context.

Ketika Parameter Menutup Field #

Sebelum melihat this bekerja, mari kita lihat dulu program yang kehilangan this. Class berikut punya constructor yang parameter dan field-nya kebetulan sama-sama bernama judul, tetapi constructor lupa memakai this:

java TanpaThis.java
public class TanpaThis {
    public static void main(String[] args) {
        BukuSalah buku = new BukuSalah("Hujan Bulan Juni");
        System.out.println("judul = " + buku.judul);
    }
}

class BukuSalah {
    String judul;

    BukuSalah(String judul) {
        judul = judul;
    }
}

Output yang Dihasilkan:

text
judul = null

Hasilnya mencetak judul = null — kejadian yang mengejutkan banyak pemula. Aturan pencarian nama di dalam method menjelaskannya: nama judul di dalam badan constructor merujuk ke parameter yang paling dekat, sehingga pernyataan judul = judul hanyalah parameter yang menugaskan nilainya ke dirinya sendiri. Field judul tidak pernah tersentuh sama sekali, dan tetap menyimpan nilai bawaan null. Compiler menerima kode ini tanpa keluhan karena baris tersebut sah secara tata bahasa — inilah jenis galat senyap yang paling sering menghantui constructor pemula.

Solusinya adalah memakai this.field untuk memaksa sisi kiri merujuk ke field milik object. Perhatikan constructor Buku berikut — pola yang sejak Chapter Constructors selalu kita tulis, dan kini maknanya terbuka penuh:

java Buku.java
class Buku {
    String judul;
    String penulis;

    Buku(String judul, String penulis) {
        this.judul = judul;
        this.penulis = penulis;
    }

    void catatKeRak(Rak rak) {
        rak.catat(this);
    }
}

Pada baris this.judul = judul;, sisi kiri this.judul menembus lapisan parameter dan merujuk ke field object aktif, sedangkan sisi kanan judul tetap merujuk ke parameter. Kedua nama yang sama kini punya dua tujuan berbeda, dan keduanya bertemu dengan benar. Ketika parameter dan field tidak berbenturan nama, awalan this menjadi opsional — tetapi konvensi Java justru sengaja menyamakan nama keduanya supaya constructor terbaca lugas di sisi pemanggil.

this Sebagai Argumen #

Wajah ketiga this tidak menembus penamaan, melainkan mengirim object aktif ke luar. Method catatKeRak di atas memanggil rak.catat(this): object Buku mengirim dirinya sendiri ke method catat milik object Rak. Lengkapi gambar dengan class Rak dan program pemanggilnya:

java Rak.java
class Rak {
    int jumlahBuku;

    void catat(Buku b) {
        jumlahBuku = jumlahBuku + 1;
        System.out.println("Rak mencatat: " + b.judul);
    }
}
public class AplikasiThis {
    public static void main(String[] args) {
        Rak rakFiksi = new Rak();
        Buku bukuA = new Buku("Laskar Pelangi", "Andrea Hirata");
        Buku bukuB = new Buku("Hujan Bulan Juni", "Sapardi Djoko Damono");

        bukuA.catatKeRak(rakFiksi);
        bukuB.catatKeRak(rakFiksi);

        System.out.println("Jumlah buku di rak: " + rakFiksi.jumlahBuku);
    }
}

Output yang Dihasilkan:

text
Rak mencatat: Laskar Pelangi
Rak mencatat: Hujan Bulan Juni
Jumlah buku di rak: 2

Mari kita bedah alur this pada program tersebut:

  1. Baris 10 pada Buku.java (rak.catat(this);): kata kunci this dipakai sebagai argumen biasa. Saat pemanggilnya bukuA, JVM mengirim referensi bukuA; saat pemanggilnya bukuB, JVM mengirim referensi bukuB — method yang sama, this yang berbeda.
  2. Baris 4 pada Rak.java (void catat(Buku b)): parameter b menerima object yang dikirim. Dari sudut pandang Rak, b adalah buku yang baru saja mendaftarkan dirinya.
  3. Baris 5-6 (jumlahBuku = jumlahBuku + 1; ...): Rak mencatat kehadiran object tersebut dan menaikkan pencacahnya — bukti bahwa object yang dikirim this benar-benar object aktif, terlihat dari judul yang tercetak.
  4. Baris 13-14 pada AplikasiThis.java (bukuA.catatKeRak(rakFiksi); dst.): dua panggilan berurutan menghasilkan dua baris pencatatan dan nilai akhir 2 — masing-masing object mengirim dirinya tanpa perlu variabel perantara.

Tiga Wajah this dalam Satu Tabel #

Bentuk pemakaianMaknaContoh pada chapter kita
this.fieldmerujuk field object aktif yang tertutup parameterthis.judul = judul;
this(...)memanggil constructor lain pada object yang sama, wajib baris pertamathis(nama, kota, 3); pada Chapter Constructor Overloading
this sebagai argumenmengirim object aktif ke method atau constructor penerimarak.catat(this);

Dengan this di tangan, kita sudah bisa menulis class yang mengelola dirinya sendiri dengan rapi. Namun seluruh field kita masih terbuka lebar — kode mana pun di luar class boleh menulis buku.stok = -50 dan merusak state. Pilar pertama OOP, encapsulation, hadir tepat untuk menutup celah tersebut: field disembunyikan, perubahan hanya boleh lewat method yang kita rancang. Itulah pokok bahasan Chapter berikutnya.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

AplikasiThis.java

Unduh berkas
java
public class AplikasiThis {
    public static void main(String[] args) {
        Rak rakFiksi = new Rak();
        Buku bukuA = new Buku("Laskar Pelangi", "Andrea Hirata");
        Buku bukuB = new Buku("Hujan Bulan Juni", "Sapardi Djoko Damono");

        bukuA.catatKeRak(rakFiksi);
        bukuB.catatKeRak(rakFiksi);

        System.out.println("Jumlah buku di rak: " + rakFiksi.jumlahBuku);
    }
}

Buku.java

Unduh berkas
java
class Buku {
    String judul;
    String penulis;

    Buku(String judul, String penulis) {
        this.judul = judul;
        this.penulis = penulis;
    }

    void catatKeRak(Rak rak) {
        rak.catat(this);
    }
}

Rak.java

Unduh berkas
java
class Rak {
    int jumlahBuku;

    void catat(Buku b) {
        jumlahBuku = jumlahBuku + 1;
        System.out.println("Rak mencatat: " + b.judul);
    }
}

TanpaThis.java

Unduh berkas
java
public class TanpaThis {
    public static void main(String[] args) {
        BukuSalah buku = new BukuSalah("Hujan Bulan Juni");
        System.out.println("judul = " + buku.judul);
    }
}

class BukuSalah {
    String judul;

    BukuSalah(String judul) {
        judul = judul;
    }
}