Topic 6 of 28 · Android Native Developer

Topic 6 : Encapsulation in Java

Lesson TL;DRTopic 6: Encapsulation in Java 📖 5 min read · 🎯 intermediate · 🧭 Prerequisites: androidbuildingblocksiactivity, androidbuildingblocksiiservices Why this matters Here's the thing — when you first st...
5 min read·intermediate·java · encapsulation · oop · android

Topic 6: Encapsulation in Java

📖 5 min read · 🎯 intermediate · 🧭 Prerequisites: android-building-blocks-i-activity, android-building-blocks-ii-services

Why this matters

Here's the thing — when you first start writing Java classes, it feels natural to just make everything public. Anyone can read it, anyone can change it. Easy. But then something breaks, and you have no idea who changed what, or when, or how. I've seen this trip up so many beginners. Encapsulation is the fix: you lock down your object's data so nothing can reach in and mess with it directly. You decide exactly what can be seen, and exactly how it gets changed. Once you feel this click, your code starts feeling much more in control.

What You'll Learn

  • What encapsulation means and why it exists in Java
  • How to declare private fields and expose them via public getter and setter methods
  • How to apply validation logic inside setters to protect data integrity
  • How to wire an encapsulated class into an Android Activity and TextView

The Analogy

Think of a bank vault. The gold inside is your class's data — valuable, sensitive, and definitely not something you want strangers touching directly. The vault door is the private keyword: it physically blocks direct access. The bank teller window is your getter and setter methods — a controlled interface where every transaction is logged, validated, and handled properly. You never hand a customer a shovel and say "help yourself"; instead, you process each request through the teller, who checks IDs, enforces limits, and keeps the ledger consistent. Encapsulation is that teller window, built right into your Java class.

Chapter 1: What Encapsulation Is

Encapsulation is the practice of bundling data (fields) and the methods that operate on that data into a single unit (a class), while simultaneously restricting direct external access to those fields. The two mechanisms that make this work in Java are:

  • The private access modifier — prevents outside code from reading or writing a field directly.
  • Public getter and setter methods — provide a controlled, intentional interface for reading and modifying that field.

Without encapsulation, any code anywhere in the codebase can do:

user.age = -999; // nothing stops this

With encapsulation, that line won't compile, and your setter can enforce that age must be positive before the assignment ever happens.

Chapter 2: Building an Encapsulated User Class

Here is a complete User class that encapsulates name and age with private fields, a constructor, and public getters and setters.

public class User {

    // Private fields — inaccessible from outside this class
    private String name;
    private int age;

    // Constructor
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Public getter for name
    public String getName() {
        return name;
    }

    // Public setter for name
    public void setName(String name) {
        this.name = name;
    }

    // Public getter for age
    public int getAge() {
        return age;
    }

    // Public setter for age — includes validation
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        } else {
            throw new IllegalArgumentException("Age must be positive");
        }
    }
}

Key points to notice:

  • name and age are private — they cannot be accessed directly from outside the User class.
  • getName() and getAge() return the values without letting callers mutate them.
  • setAge() validates the incoming value before accepting it; passing 0 or a negative number throws an IllegalArgumentException immediately, so invalid state can never be stored.
  • setName() accepts any non-null String — no special guard needed here, but you could add one.
classDiagram
    class User {
        -String name
        -int age
        +User(name, age)
        +getName() String
        +setName(name)
        +getAge() int
        +setAge(age)
    }
    note for User "Private fields\nPublic interface"

Chapter 3: Using the Encapsulated Class in an Android Activity

Now let's wire the User class into a real Android Activity. The activity creates a User object, updates its fields through the setters, then displays the result in a TextView.

Activity code (MainActivity.java)

public class MainActivity extends AppCompatActivity {

    private TextView userTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        userTextView = findViewById(R.id.user_text_view);

        // Create a new User object via the constructor
        User user = new User("Alice", 25);

        // Update user details through the public setters
        user.setName("Bob");
        user.setAge(30);

        // Read back through getters and display in the TextView
        String userDetails = "Name: " + user.getName() + ", Age: " + user.getAge();
        userTextView.setText(userDetails);
    }
}

Layout XML (activity_main.xml)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/user_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="User Details"
        android:textSize="18sp" />

</RelativeLayout>

When the app runs, the TextView in the center of the screen displays: Name: Bob, Age: 30 — the values set through the controlled setter interface, not by poking at fields directly.

Chapter 4: Benefits of Encapsulation

Three concrete advantages that encapsulation brings to every Android project:

  1. Improved Security — Restricting direct access to a class's internals prevents unauthorized reads and accidental (or malicious) overwrites. Nobody can set age = -1 from another Activity.

  2. Enhanced Maintainability — Because all field access goes through a single choke point (the getter/setter), you can change the internal representation of a field — say, switching from int age to a LocalDate birthDate — without touching any code outside the class. The public interface stays the same.

  3. Increased Flexibility — Setters are the right place to add validation, logging, formatting, or event notifications. The setAge guard above is a simple example; in production you might also fire a LiveData update or write to a database there.

🧪 Try It Yourself

Task: Add a third encapsulated field, email, to the User class. The setter must reject any string that doesn't contain an @ character by throwing an IllegalArgumentException. Then update MainActivity to set an email on your User and display it alongside the name and age in the TextView.

Success criterion: Running the app shows Name: Bob, Age: 30, Email: bob@example.com on screen. Passing "notanemail" to setEmail() should crash with the message "Invalid email address" — confirm this in Logcat by temporarily calling it with a bad value.

Starter snippet:

// Inside the User class
private String email;

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    if (email != null && email.contains("@")) {
        this.email = email;
    } else {
        throw new IllegalArgumentException("Invalid email address");
    }
}

🔍 Checkpoint Quiz

Q1. What is the primary purpose of marking a class field private in Java?

A) To make the field available only within the same package
B) To prevent any code outside the class from accessing the field directly
C) To stop the field from being garbage-collected
D) To make the field read-only everywhere

Q2. Given the User class above, what happens when the following line executes?

user.setAge(-5);

A) age is set to -5 without error
B) age is set to 0 as a fallback
C) An IllegalArgumentException is thrown
D) A NullPointerException is thrown

Q3. A teammate writes this code in another class:

User u = new User("Priya", 28);
System.out.println(u.age); // direct field access

What is the result, and how do you fix it?

Q4. You need to log every time a user's name changes. Where in the encapsulated User class is the correct place to add that logging call, and why?

A1. B) — private restricts access to within the declaring class only. Package-private is the default (no modifier); private is stricter.

A2. C) — setAge checks if (age > 0) before assigning; -5 fails that check and the else branch throws IllegalArgumentException("Age must be positive").

A3. The line fails to compile with "age has private access in User." Fix it by accessing the field through the getter: System.out.println(u.getAge());

A4. Inside setName(), because that method is the single controlled entry point for all name changes. Any code that changes the name must go through setName, so a log statement there is guaranteed to fire every time — unlike placing it at every call site, which is error-prone and easy to miss.

🪞 Recap

  • Encapsulation bundles fields and methods into one class and hides fields behind private to prevent uncontrolled access.
  • Public getter methods expose field values for reading; public setter methods expose them for writing — through a controlled interface.
  • Setters are where you enforce validation rules, such as rejecting negative ages or malformed email addresses.
  • Using an encapsulated class in an Android Activity means creating objects via constructors and reading/writing through getters and setters, never touching fields directly.
  • The payoff is code that is more secure, easier to maintain, and easier to extend without ripple-effect bugs.

📚 Further Reading

Like this topic? It’s one of 28 in Android Native Developer.

Block your seat for ₹2,500 and join the next cohort.