Lesson 20 of 20

Access Modifiers

Access Modifiers

Java has four access levels that control visibility of classes, fields, and methods. Understanding them is essential for proper encapsulation.

The Four Access Levels

ModifierClassPackageSubclassWorld
publicYesYesYesYes
protectedYesYesYesNo
(default)YesYesNoNo
privateYesNoNoNo

Private

private members are only accessible within the declaring class. This is the most restrictive level and the default choice for fields:

class BankAccount {
    private double balance;

    public double getBalance() { return balance; }
    public void deposit(double amount) {
        if (amount > 0) balance += amount;
    }
}

By making balance private, we force all access through methods that can validate input. This is the core of encapsulation.

Package-Private (Default)

When you write no modifier, the member is visible to all classes in the same package. This is called package-private or default access:

class Helper {
    int count = 0;           // package-private field
    void increment() { count++; } // package-private method
}

Use this when classes within the same package need to collaborate closely, but outsiders should not depend on the implementation.

Protected

protected is like package-private but also grants access to subclasses in other packages:

class Shape {
    protected String color;

    protected void describe() {
        System.out.println("A " + color + " shape");
    }
}

class Circle extends Shape {
    Circle(String color) {
        this.color = color;  // OK — subclass access
    }
}

Public

public members are accessible from anywhere. Use this for the API your class exposes to the outside world.

Best Practices

  1. Start with private — only widen access when you have a clear reason.
  2. Expose behavior, not data — provide methods instead of public fields.
  3. Use protected sparingly — it couples subclasses to implementation details.
  4. Prefer package-private for internal helpers — they can change without breaking external code.

Your Task

  1. Create a class User with:

    • A private String name and private String email field
    • A public constructor taking both values
    • A public String getName() getter
    • A public String getEmail() getter
    • A private String maskEmail() method that returns the email with everything before @ replaced by "***" (e.g. "alice@example.com""***@example.com")
    • A public String getPublicProfile() that returns name + " <" + maskEmail() + ">"
  2. Create a class Admin that extends User with:

    • A protected String role field
    • A constructor taking name, email, and role
    • A public String getPublicProfile() override that returns name + " [" + role + "] <" + maskEmail() + ">" — but since maskEmail() is private, you must call getEmail() and do the masking yourself
  3. In main, create a User("Alice", "alice@example.com") and an Admin("Bob", "bob@corp.io", "SuperAdmin"). Print each one's public profile.

TeaVM (WASM) loading...
Loading...
Click "Run" to execute your code.