ProgrammingJava Developer

How is access control to class members organized in Java and what pitfalls are there when using different access modifiers?

Pass interviews with Hintsage AI assistant

Answer.

Background:

Access control for data and methods in Java was introduced to ensure encapsulation and protect the internal structure of classes. This is an essential part of OOP, allowing for the hiding of implementation and preventing unauthorized modification of object states.

Problem:

Different access modifiers — public, protected, (package-private), private — limit the visibility of class members in different ways, which is often not obvious. An incorrectly chosen level can lead to bugs, undesirable privilege escalation, and a violation of encapsulation.

Solution:

Use the minimally required access modifier for each field or method. Java supports:

  • private — accessible only within the same class
  • (package-private) — if no modifier is specified, accessible only within the package
  • protected — within the package and in subclasses (even if they are outside the package)
  • public — accessible everywhere

Code example:

public class Dog { private String name; // visible only inside Dog String breed; // package-private protected int age; // visible in package and in subclasses public void bark() { // accessible from any code System.out.println("Woof!"); } }

Key Features:

  • By default, package-private is chosen
  • protected differs in Java from C++ (in Java the visibility is package-specific!)
  • private does not protect against access through reflection, but one should not rely on that

Tricky Questions.

Can an inner class access all private fields of its outer class?

Yes, an inner class has complete access to all fields and methods of its outer class, even private ones. Conversely, the outer class can access private members of the inner class if it has an instance of it.

Can a protected class member be accessible outside the package without inheritance?

No. Outside the package, protected is convenient only for inheritors. Simply accessing it through an object of the class in another package is not allowed.

What happens if a class is not declared public but is imported from another package?

A class with package-private access cannot be imported and explicitly used outside its package. An attempt to access it from code in another package will result in a compilation error.

Common Mistakes and Anti-Patterns

  • Making class fields public, violating encapsulation
  • Relying on protected as a "safe" access level without considering package visibility
  • Using package-private without understanding that it is visible to all classes in the package

Real Life Example

Negative case

All fields of a DTO class are marked as public for easy access.

Pros:

  • Fast, no need to write getter/setter

Cons:

  • Violation of encapsulation, unexpected data modification is possible
  • Harder to control object states

Positive case

Private fields and public access methods are used.

Pros:

  • Control over the internal state of the object
  • Easier to maintain invariants and debug

Cons:

  • A bit more code (getter/setter)