Private State & Methods

The Course
•
4 min read

A private field cannot be accessed directly from another top-level class. Public methods can expose useful operations without exposing every internal assignment. This is encapsulation: the object owns rules about its state. A getter reads a field; a setter assigns one. You do not need either automatically for every field. The public operations form the class’s API: what other code can call and the behavior it can rely on.

A session’s planned duration can stay fixed while completion changes. Instead of allowing any caller to write done, expose complete(). Calling it twice should still mean completed, not toggle the state back or add time twice. This operation is idempotent: repeating it has the same final effect as doing it once.

Choose what callers should be able to do

Return information through methods such as remaining(), and update state through methods named after an action. A method returning false can report that a proposed change was rejected. On Day 6, exceptions will offer another way to signal invalid input. Both approaches need a clear rule about whether state changed.

The keyword public allows the model’s methods to be called by other classes. For now, keep all classes in the supplied workspace and use public for the operations intended for callers, and private for the data they should not assign directly. Other access rules can wait until you need to organize a larger project.

Complete once, read many times Java
public class Main {
    public static void main(String[] args) {
        Session session = new Session(25);
        System.out.println(session.remaining());

        session.complete();
        session.complete();

        System.out.println(session.remaining());
    }
}

class Session {
    private final int minutes;
    private boolean done;

    Session(int minutes) {
        this.minutes = minutes;
    }

    public void complete() {
        done = true;
    }

    public int remaining() {
        if (done) {
            return 0;
        }

        return minutes;
    }
}
Check your prediction
25
0

The completion operation assigns a fact; it does not flip the boolean. The second call leaves the same state as the first. A caller can ask for remaining time without learning how the boolean is stored.

Reject an update without changing state Java
public class Main {
    public static void main(String[] args) {
        Budget budget = new Budget();
        System.out.println(budget.add(-5));
        System.out.println(budget.add(10));
        System.out.println(budget.total());
    }
}

class Budget {
    private int minutes;

    public boolean add(int amount) {
        if (amount < 0) {
            return false;
        }

        minutes += amount;
        return true;
    }

    public int total() {
        return minutes;
    }
}
Check your prediction
false
true
10

Validation occurs before mutation. If you added the amount before testing it, the false result would conceal a changed budget. The contract includes both the returned boolean and the state afterward.

Compiler error: private access Java
public class Main {
    public static void main(String[] args) {
        Secret secret = new Secret();
        System.out.println(secret.value);
    }
}

class Secret {
    private int value = 25;
}
Read the diagnostic

Main cannot read a private field declared by the separate top-level Secret class. Expose an intentional method if callers need this information. Do not remove private merely to silence the error without deciding the API.

Your turn

Exercise

Protect a counter

Implement Counter with a private int count, public void increment() and public int current(). Create two instances, increment the first twice and print 2 then 0. main must not access the count field directly.

Your workspace Java
public class Main {
    public static void main(String[] args) {
        // Use methods to change and inspect the counters.
    }
}

class Counter {
    private int count;
    // Define the public operations.
}
Hint 1: the idea

Keep the field private and provide one method for mutation and another for observation.

Hint 2: a first step

increment has no returned result, while current returns an int. Neither should be static because each counter owns its count.

Show one solution
public class Main {
    public static void main(String[] args) {
        Counter first = new Counter();
        Counter second = new Counter();

        first.increment();
        first.increment();

        System.out.println(first.current());
        System.out.println(second.current());
    }
}

class Counter {
    private int count;

    public void increment() {
        count++;
    }

    public int current() {
        return count;
    }
}
2
0

Change it and explain

Add a reset() method and write a check that resetting one object does not affect another. Then decide whether reset is part of the actual brief or an optional extension: a smaller API can be easier to understand and test.

Use methods to enforce meaningful rules, not just to disguise arbitrary assignment. A complete() method communicates more intent than setDone(boolean) when the project never needs to make a completed session incomplete.

Was this article helpful?

Your response is saved on this device.