Insights into Company
← Java

Access Modifiers

Understand the idea. Compare it. Explain it. Test yourself.

Question 1 of 9

What are access modifiers?

Solution and explanation

What they are

Access modifiers control where a class, constructor, method or field can be used from. They are Java's main tool for encapsulation: hide internal details, expose only what callers need.

The four levels

ModifierSame classSame packageSubclass (other package)Everywhere
privateYesNoNoNo
(none) package-privateYesYesNoNo
protectedYesYesYes (through inheritance)No
publicYesYesYesYes

Example

package com.portal.payment;

public class PaymentService {                 // usable everywhere
    private String apiKey;                    // only inside this class
    int retryCount = 3;                       // package-private: classes in com.portal.payment
    protected void log(String msg) { }        // package + subclasses anywhere
    public boolean pay(double amount) {       // public API
        return charge(amount);
    }
    private boolean charge(double amount) { return true; }   // implementation detail
}

Where each can be used

  • Top-level classes: only public or package-private.
  • Members (fields, methods, constructors, nested classes): all four.
  • Interface methods are public by default; interface fields are public static final.

Java 9 modules

With JPMS, even public classes are visible to other modules only if their package is exported in module-info.java, which adds a layer above these modifiers.

Rule of thumb: make everything as private as possible, and widen access only when there is a reason.

Practice explaining this
Question 2 of 9

What is public access?

Solution and explanation

Meaning

A public class, method, constructor or field is accessible from any class in any package (and, with modules, from any module that reads an exported package).

package com.portal.util;

public class CurrencyFormatter {
    public static final String SYMBOL = "₹";

    public String format(double amount) {
        return SYMBOL + String.format("%,.2f", amount);
    }
}

// In another package
import com.portal.util.CurrencyFormatter;
String text = new CurrencyFormatter().format(125000);   // ₹1,25,000.00 style output (locale dependent)

Rules

  • A source file can contain at most one public top-level class, and the file name must match it.
  • public static void main(String[] args) must be public so the JVM can call it from outside.
  • Overriding methods cannot reduce visibility: if a parent method is public, the override must be public.

When to use

  • The class's API: methods other parts of the system are meant to call.
  • Constants intended to be shared (public static final).

When not to use

Avoid public mutable fields (public double balance;). Anyone can set it to an invalid value and you cannot add validation later without breaking callers. Expose behaviour through public methods instead.

Practice explaining this
Question 3 of 9

What is private access?

Solution and explanation

Meaning

A private member is accessible only inside the class (top-level class including its nested classes) where it is declared. It is the most restrictive access level.

public class BankAccount {
    private double balance;                       // hidden state
    private final List<String> history = new ArrayList<>();

    public void withdraw(double amount) {
        validate(amount);
        balance -= amount;
        history.add("Withdraw " + amount);
    }

    public double getBalance() { return balance; }      // controlled read access

    private void validate(double amount) {              // helper not part of the public API
        if (amount <= 0 || amount > balance) throw new IllegalArgumentException("Invalid amount");
    }
}

BankAccount acc = new BankAccount();
// acc.balance = 1_000_000;   // compile error: balance has private access

Rules

  • Private methods are not inherited and cannot be overridden; a method with the same signature in a subclass is a new method.
  • Private members of a nested class are accessible to the outer class and vice versa.
  • Top-level classes cannot be private.
  • Private constructors control instantiation (Singleton, utility classes, factories).
  • Interfaces can have private methods since Java 9, to share code between default methods.

Why use it

  • Protects invariants (balance can never go negative).
  • Lets you change the internal representation without breaking other code.
  • Reduces what other developers need to understand.
Practice explaining this
Question 4 of 9

What is protected access?

Solution and explanation

Meaning

A protected member is accessible:

  1. inside its own class,
  2. from any class in the same package, and
  3. from subclasses in other packages, through inheritance.
package com.portal.base;
public class Notification {
    protected String recipient;
    protected void send(String message) { System.out.println("To " + recipient + ": " + message); }
}

package com.portal.sms;
import com.portal.base.Notification;

public class SmsNotification extends Notification {
    public void alert() {
        recipient = "9876543210";          // OK: inherited protected field
        send("Interview scheduled");      // OK: inherited protected method
    }

    void test(Notification other) {
        // other.send("x");                // compile error: not through inheritance (different package)
        SmsNotification same = new SmsNotification();
        same.send("ok");                   // OK: reference of the subclass type
    }
}

The subtle rule

In a different package, a subclass can access a protected member only through references of its own type (or its subtypes), not through a plain parent-type reference.

Typical uses

  • Template Method pattern: the parent defines protected abstract steps that subclasses implement.
  • Hooks that subclasses may override (protected void onSave()).
  • Object.clone() and Object.finalize() are protected.

Overriding

An override may keep protected or widen it to public, but cannot make it package-private or private.

Practice explaining this
Question 5 of 9

What is package-private access?

Solution and explanation

Meaning

When no access modifier is written, the member or class is package-private (also called default access). It is visible only to classes in the same package.

package com.portal.jobs;

class JobRanker {                         // package-private class: helper not visible outside the package
    double score(Job job) { return job.getViews() * 0.3 + job.getApplies() * 0.7; }
}

public class JobSearchService {
    private final JobRanker ranker = new JobRanker();     // same package: OK
    public List<Job> search(String q) { /* uses ranker */ return List.of(); }
}

package com.portal.web;
// new JobRanker();     // compile error: JobRanker is not public in com.portal.jobs

Key points

  • Subclasses in other packages cannot access package-private members.
  • Packages are not hierarchical: com.portal.jobs.internal cannot see package-private members of com.portal.jobs.
  • Interface members are never package-private: methods default to public.

Why use it

  • Hide helper classes and methods that are implementation details of a package, while still sharing them inside the package.
  • Unit tests placed in the same package (the usual Maven layout, src/test/java/com/portal/jobs) can access package-private methods, which is convenient for testing without making them public.
  • Spring Boot 2.x+ test classes and JUnit 5 test methods are often package-private.
Practice explaining this
Question 6 of 9

Which modifier is most restrictive?

Solution and explanation

Answer

private is the most restrictive: the member is visible only inside its own class. public is the least restrictive.

Most restrictive → least restrictive
private  <  package-private (no modifier)  <  protected  <  public
ModifierClassPackageSubclass in other packageWorld
privateYesNoNoNo
package-privateYesYesNoNo
protectedYesYesYesNo
publicYesYesYesYes

Why the order matters: overriding

An overriding method cannot be more restrictive than the method it overrides.

class Parent { protected void run() { } }
class Child extends Parent {
    @Override public void run() { }          // OK: widening protected → public
    // @Override void run() { }              // error: attempting to assign weaker access privileges
}

Interview tip

"Protected is more restrictive than package-private" is a common wrong answer. Protected includes everything package-private allows, plus subclass access from other packages, so it is less restrictive.

Practice explaining this
Question 7 of 9

Can a method or constructor be private?

Solution and explanation

Answer

Yes, both can be private.

Private methods

Used as internal helpers that are not part of the class's API.

public class InvoiceService {
    public Invoice create(Order order) {
        double tax = calculateGst(order.getAmount());
        return new Invoice(order.getId(), order.getAmount() + tax);
    }

    private double calculateGst(double amount) {     // hidden helper
        return amount * 0.18;
    }
}

Characteristics:

  • Not inherited, so they cannot be overridden (a same-named method in a subclass is independent).
  • Resolved at compile time (static binding), and the JIT can inline them easily.
  • Since Java 9 interfaces can have private methods shared by default methods.

Private constructors

Used to control object creation:

public final class Validators {
    private Validators() { }                         // no instances of a utility class
    public static boolean isPan(String s) { return s.matches("[A-Z]{5}[0-9]{4}[A-Z]"); }
}

public class Connection {
    private Connection(String url) { }
    public static Connection open(String url) { return new Connection(url); }   // static factory
}

Uses: Singleton, utility classes, static factory methods, builders and enums (enum constructors are always private).

Side effect: a class whose only constructors are private cannot be subclassed by other classes (except its own nested classes).

Practice explaining this
Question 8 of 9

What is the difference between private and protected?

Solution and explanation

Comparison

Featureprivateprotected
Same classYesYes
Same package, other classNoYes
Subclass in another packageNoYes, through inheritance
Inherited by subclassesNo (exists in the object but not accessible)Yes
Can be overridden (methods)NoYes
Can be used on top-level classNoNo
PurposeHide implementation completelyShare with subclasses (extension points)

Example

public class Report {
    private String rawData;                         // only Report can touch it
    protected String title = "Monthly report";      // subclasses can customise it

    protected String format() { return title.toUpperCase(); }   // hook for subclasses
    private void loadData() { rawData = "…"; }                   // internal step
}

public class SalesReport extends Report {
    public SalesReport() {
        title = "Sales report";        // OK: protected
        // rawData = "x";              // error: private
    }

    @Override
    protected String format() {        // OK: overriding a protected method
        return "[SALES] " + super.format();
    }
}

Guideline

Start with private. Make something protected only when you are deliberately designing the class for extension, because every protected member becomes a contract that subclasses may depend on.

Practice explaining this
Question 9 of 9

Why should fields usually be private?

Solution and explanation

Short answer

Private fields enforce encapsulation: the object controls its own state, so it can guarantee its rules (invariants), and its internal representation can change without breaking other code.

Problem with public fields

public class Account {
    public double balance;
}
Account a = new Account();
a.balance = -50000;          // invalid state, nothing can stop it

Private fields with controlled access

public class Account {
    private double balance;

    public double getBalance() { return balance; }

    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("Deposit must be positive");
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount > balance) throw new IllegalStateException("Insufficient funds");
        balance -= amount;
    }
}

Benefits

  1. Validation: every change goes through methods that check rules.
  2. Flexibility: you can change double balance to BigDecimal or long paise internally; callers using getBalance() are unaffected.
  3. Read-only or write-only: provide only a getter, or only a setter.
  4. Thread safety: synchronise inside the methods that change state.
  5. Debugging: put a breakpoint or log in one setter instead of searching all assignments.
  6. Lazy loading and derived values: a getter can compute or load values on demand.
  7. Immutability: private final fields with no setters produce immutable objects that are safe to share.

Exceptions

  • public static final constants (MAX_SIZE) are fine.
  • Records expose components through accessor methods, with fields still private and final.
Practice explaining this