What is the difference between public, protected, package-private and private in Java?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Java access modifiers define who can see a class member and from where. They are central to encapsulation because they let you expose only the API that other code should depend on while hiding implementation details that should remain internal.
The Four Access Levels
At the member level, Java gives you four practical visibility levels:
- '
public' - '
protected' - package-private, which is what you get when no modifier is written
- '
private'
A compact example helps show the differences.
What public Means
public is the widest visibility. Any code that can see the containing class can access a public member.
That is appropriate for stable API surface such as service methods, DTO getters, or utility methods that are intended for external callers. Public members become part of the contract other code depends on, so they should be chosen carefully.
What protected Means
protected is often misunderstood. It gives access in two cases:
- code in the same package can access it
- subclasses can access it, even from a different package
That means protected is broader than "subclasses only." Package peers also get access.
If a non-subclass in another package tries to read owner, that access is not allowed.
What Package-Private Means
If you omit an access modifier entirely, the member is package-private. That means only code in the same package can use it.
This is an excellent default for implementation details that should be shared across related classes but not leaked outside the package. It helps keep APIs smaller without forcing everything into private.
Package-private is also the narrowest visibility available for top-level classes when you do not want them to be public.
What private Means
private is the narrowest access level. The member is visible only inside the declaring class itself.
Use private for internal state, helper methods, and invariants you want to control tightly.
This protects the class from outside code changing value directly and breaking assumptions.
A Top-Level Class Limitation
One subtle rule trips people up: top-level classes cannot be protected or private. A top-level class can be only public or package-private.
protected and private are valid for nested classes, methods, constructors, and fields, but not for ordinary top-level class declarations.
Common Pitfalls
The most common mistake is thinking protected means subclass-only. In Java it also includes same-package access, which is broader than many developers expect.
Another mistake is overusing public. Every public member increases coupling and makes later refactoring harder. Start narrow and widen only when another package truly needs access.
Be careful with package-private when packages are large or poorly organized. If unrelated classes share a package, package-private can expose more than you intended.
Finally, avoid exposing fields directly unless there is a strong reason. Access modifiers are most effective when they protect behavior and invariants, not just raw data.
Summary
- '
publicis visible everywhere the class itself is visible.' - '
protectedis visible to the same package and to subclasses in other packages.' - Package-private is the default when no modifier is present and limits access to the same package.
- '
privaterestricts access to the declaring class only.' - Top-level classes can be only
publicor package-private.
Related reading
- / and / in Java Comments
- (double colon) operator in Java 8
- Plus sign not encoded with RestTemplate using String URL, interpreted as space
- a bean of type 'org.springframework.mail.javamail.JavaMailSender' that could not be found
- A default binder has been requested, but there are no binders available for ''org.springframework.cloud.stream.messaging.DirectWithAttributesChannel''
- A failure occurred while executing com.android.build.gradle.internal.tasks
- A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
- A for-loop to iterate over an enum in Java

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.