Belajar OOP dengan Java - Encapsulation & Access Modifiers
Episode 6 of 23

Belajar OOP dengan Java - Encapsulation & Access Modifiers

Menerapkan pilar pertama OOP: access modifiers public, protected, package-default dan private, lalu pola encapsulation dengan field private plus getter/setter, object immutable berbasis final, dan JavaBeans pattern yang dipakai framework di dunia nyata.

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Di episode 4 dan 5 kita membuat object dengan field yang terbuka — siapa pun bisa langsung menulis mobil.warna = "biru". Episode ini mengubah itu. Kita masuk ke pilar pertama OOP: encapsulation — menyembunyikan detail internal dan hanya membuka akses yang aman.

Mengapa encapsulation penting? Karena field publik adalah undangan bug. Siapa pun bisa memasukkan nilai tidak valid (harga = -500), dan begitu object rusak, sulit menemukan siapa yang merusaknya. Encapsulation bukan hanya "menyembunyikan", tetapi menjaga invarian — memastikan object tidak pernah masuk ke keadaan yang tidak sah.

Access Modifiers

Empat tingkatan akses di Java, dari paling terbuka ke paling ketat:

ModifierAkses dariKapan dipakai
publicSemua class di mana punAPI publik yang aman diekspos
protectedPackage yang sama + subclassAPI untuk pewaris (episode 7)
(default/package)Hanya package yang samaImplementasi internal package
privateHanya class itu sendiriDetail internal, state sejati
JavaEmpat access modifier
public class Contoh {
    public int untukSemua;
    protected int untukTurunan;
    int untukPackage;
    private int rahasia;
}

Analogi yang mudah: rumah. public adalah halaman depan (semua orang boleh masuk), protected adalah kamar keluarga (keluarga + tamu tertentu), default adalah ruang tamu (yang tahu alamatnya), private adalah kamar pribadi (hanya pemiliknya).

Aturan Praktis

  • Field seharusnya private. Hampir selalu.
  • Methodpublic jika bagian dari API, private jika helper internal.
  • Mulai dari yang paling ketat (private), lalu longgarkan hanya jika ada kebutuhan nyata.

Mengapa protected dan default jarang dipakai di codebase modern? Karena keduanya melanggar "segel" encapsulation tanpa keuntungan yang jelas. Bahasa seperti Rust dan Go bahkan tidak punya konsep protected — sinyal bahwa akses lintas class seharusnya disengaja, bukan karena kebetulan.

Encapsulation dengan Getter/Setter

Pola Dasar

Enkapsulasi = field private + method akses terkontrol:

JavaEncapsulation dasar
public class Produk {
    private String nama;
    private double harga;
 
    public String getNama() {
        return nama;
    }
 
    public void setNama(String nama) {
        this.nama = nama;
    }
 
    public double getHarga() {
        return harga;
    }
 
    public void setHarga(double harga) {
        if (harga < 0) {
            throw new IllegalArgumentException("Harga tidak boleh negatif");
        }
        this.harga = harga;
    }
}

Perhatikan setHarga: ia memvalidasi sebelum menyimpan. Field tidak bisa diisi -500 karena setter menolaknya. Inilah wujud nyata "menjaga invarian" — akses tidak dibuka langsung, melainkan melalui gerbang yang berisi aturan.

Getter vs Field Publik: Apa Bedanya?

Jika getter/setter cuma memakai kembali field, kenapa tidak langsung public saja? Tiga alasan:

  1. Validasi — setter bisa menolak nilai tidak valid (contoh di atas).
  2. Kontrol masa depan — field bisa berubah struktur internalnya (misal ganti dari double ke BigDecimal) tanpa memecah pemanggil, karena API getter/setter tetap.
  3. Logika tambahan — bisa menambah hitungan, logging, atau reaksi pada perubahan nilai.

Inilah kunci konseptual: getter/setter adalah kontrak, field adalah detail implementasi. Pemanggil bergantung pada kontrak, bukan pada field.

Immutable Object dengan final

Kadang object justru tidak perlu diubah sama sekali. Immutability — object yang tidak bisa berubah setelah dibuat — menghilangkan seluruh kelas bug: race condition, perubahan tidak sengaja, dan state yang tidak konsisten.

JavaObject immutable
public final class Titik {
    private final int x;
    private final int y;
 
    public Titik(int x, int y) {
        this.x = x;
        this.y = y;
    }
 
    public int getX() {
        return x;
    }
 
    public int getY() {
        return y;
    }
}

Aturan immutable object:

  • Semua field private final — diset sekali di constructor, tidak pernah berubah.
  • Tidak ada setter.
  • Class di-declare final agar tidak bisa di-subclass (mencegah subclass menambah state yang bisa diubah).
  • Jika ada field bertipe object yang mutable (misal List), jangan ekspos reference aslinya — kembalikan salinan (defensive copy, episode 18).

Bandingkan dengan object mutable: Titik immutable tidak bisa "rusak" setelah lahir. Setiap perubahan perlu membuat object baru:

java
Titik pindah = new Titik(titik.getX() + 5, titik.getY());

Di episode 10, record akan memberi immutability ini secara gratis — dan di episode 18 kita akan lihat mengapa immutable menjadi best practice produksi.

JavaBeans Pattern

JavaBeans adalah konvensi (bukan keyword) yang dipakai framework Java selama puluhan tahun:

  • Class memiliki constructor no-arg (default).
  • Semua properti private + getter/setter publik.
  • Setter mengikuti penamaan setNamaProperti, getter getNamaProperti.
JavaJavaBeans pattern
public class User implements java.io.Serializable {
    private String email;
    private String nama;
 
    public User() {}
 
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public String getNama() { return nama; }
    public void setNama(String nama) { this.nama = nama; }
}

JavaBeans lahir dari era reflection-heavy frameworks (JSP, Spring) yang butuh cara menciptakan object kosong lalu mengisi properti lewat setter. Kelemahannya kini jelas: object bisa berada dalam keadaan "setengah terisi". Karena itu Java modern lebih memilih constructor penuh (episode 5) atau record (episode 10) — object lahir lengkap, bukan diisi kemudian.

Warning

Jangan pernah menulis getter untuk field mutable lalu mengembalikan reference-nya langsung. Contoh: public List<String> getNama() { return listNama; } — pemanggil bisa memodifikasi list dari luar, merusak encapsulation. Kembalikan salinan atau view tak-ubah (Collections.unmodifiableList).

Latihan Terpadu

JavaEncapsulation lengkap
public class Rekening {
    private final String pemilik;
    private double saldo;
 
    public Rekening(String pemilik, double saldoAwal) {
        if (pemilik == null || pemilik.isBlank()) {
            throw new IllegalArgumentException("Pemilik wajib diisi");
        }
        this.pemilik = pemilik;
        this.saldo = Math.max(saldoAwal, 0);
    }
 
    public String getPemilik() {
        return pemilik;
    }
 
    public double getSaldo() {
        return saldo;
    }
 
    public void deposit(double nominal) {
        if (nominal <= 0) {
            throw new IllegalArgumentException("Nominal harus positif");
        }
        saldo += nominal;
    }
}

Perhatikan: pemilik final (tidak berubah), saldo hanya bisa berubah lewat deposit yang memvalidasi. Tidak ada jalan untuk membuat rekening "rusak" — invarian dijaga sejak constructor. Ini encapsulation + immutability bekerja bersama.

Tip

Jika setter kalian tidak melakukan validasi atau logika apa pun (hanya this.x = x), pertimbangkan untuk menghilangkan setter sama sekali dan jadikan field-nya final. Setter tanpa aturan hanyalah public field yang lebih bertele-tele — dan object immutable lebih aman.

Penutup

Inti yang harus dibawa pulang:

  • Empat access modifier: public, protected, default (package), private — mulai dari yang paling ketat.
  • Encapsulation = field private + akses terkontrol lewat getter/setter yang memvalidasi.
  • Object immutable (final fields, tanpa setter, class final) menghilangkan seluruh kelas bug.
  • JavaBeans adalah konvensi lama; Java modern lebih suka constructor penuh atau record.
  • Jangan ekspos reference internal yang mutable — kembalikan salinan atau view tak-ubah.

Di episode 7 selanjutnya kita akan membahas inheritanceextends, super, method overriding, @Override, dan peran Object sebagai root class, plus pitfall favorit composition over inheritance. Sampai jumpa di episode 7!

Belajar OOP dengan Java - Encapsulation & Access Modifiers | Belajar OOP