← Back to Home

Access Control Rules

Access control rules in Java define who can access what—classes, constructors, variables, and methods—across classes, packages, and inheritance hierarchies. They are central to encapsulation, security, and clean API design.

The Four Access Levels (Least → Most Accessible)

private  <  default (package-private)  <  protected  <  public
          

Where Access Modifiers Can Be Applied

Target Allowed Modifiers
Top-level class public, default
Member class all four
Methods all four
Variables (fields) all four
Constructors all four

Core Visibility Matrix (Interview Favorite)

Modifier Same Class Same Package Subclass (diff pkg) Everywhere
private
default
protected ✔*
public

* Protected nuance: accessible in a subclass only via inheritance (not via a parent reference from outside the package).

Detailed Rules by Modifier

1) private

  • Scope: within the declaring class only
  • Not inherited
  • Best for fields and internal helpers
class A {
    private int x;
}
          

2) default (package-private)

  • Scope: same package
  • Not accessible from other packages (even subclasses)
class A { int y; } // default
          

3) protected

  • Scope: same package OR subclasses in other packages
  • Subclass rule: access through this/inheritance, not through a parent instance
package p1;
public class Parent { protected int v; }

package p2;
public class Child extends Parent {
    void ok() { System.out.println(v); } // ✅
    void bad(Parent p) {
        // System.out.println(p.v); // ❌ outside package via parent ref
    }
}
          

4) public

  • Scope: everywhere
  • Use for APIs and entry points
public class Service {
    public void run() {}
}
          

Class-Level Access Rules

  • Top-level classes: only public or default
  • One public class per file, filename must match
public class A {}   // A.java
class Helper {}     // default
          

Constructor Access Control

  • Controls who can create objects
  • Common patterns:
  • private constructor → Singleton / Utility
  • protected → framework-controlled instantiation
class Util {
    private Util() {} // no instances
}
          

Access Control with Inheritance (Key Points)

  • private members: not inherited
  • Overriding rules:
  • Cannot reduce visibility
  • Can increase visibility
class P { protected void f() {} }
class C extends P { public void f() {} } // ✅
          

Packages as Visibility Boundaries

  • default and protected rely on package boundaries
  • Sub-packages are independent; no implicit access
com.app
 ├─ service
 └─ util   // util ≠ service
          

Best Practices (Production-Grade)

  • Use the most restrictive modifier possible
  • Fields → private
  • Methods → expose minimal public API
  • Prefer specific protected over public in frameworks
  • Avoid default for public libraries (ambiguous API surface)

Common Pitfalls

  • Assuming protected == package-only
  • Accessing protected via parent reference across packages
  • Overexposing fields as public
  • Expecting sub-packages to inherit access

Interview-Ready Answers

Short:

Access control rules define the visibility of classes and members using private, default, protected, and public.

Detailed:

Java access control governs where classes and members can be accessed—within a class, package, subclass, or globally. private restricts to the class, default to the package, protected adds subclass access across packages (via inheritance), and public allows universal access. Proper use enforces encapsulation and secure APIs.

Key Takeaway

Access control is the gatekeeper of encapsulation. Design with the smallest visible surface area to achieve safe, maintainable, and scalable Java code.