In Java, access to fields, methods, and classes is controlled using access modifiers: private, default (package-private), protected, public.
History of the issue:
Early versions of Java used strict object encapsulation. Different levels of access were introduced for flexibility to support both complete closure and extensibility (inheritance and access within the package).
Problem:
Choosing the wrong modifier can lead to encapsulation violations, problems with inheritance, testing issues, or even security bugs if data becomes publicly accessible by mistake.
Solution:
Use the most restrictive modifier that your architecture allows. Fields are usually made private, with access provided through getter/setter methods. Methods are made public only if they are part of the API, and for extensibility — protected.
Code example:
public class Person { private String name; // private field protected int age; // accessible in package and subclasses String email; // package-private public String getName() { return name; } }
Key features:
private — accessible only within the classprotected — plus access for subclasses even from other packagespublic — accessible to everyoneCan access modifiers be applied to local variables?
No. Access modifiers apply only to classes, methods, and fields/nested classes, but not to local variables.
Can a class inside a method be declared with the public modifier?
No. A local class cannot be declared with an access modifier; it always has visibility within the method.
Is a protected member accessible to a subclass in another package?
Yes, protected members are accessible to subclasses, even if they are in other packages, but not to regular classes in another package.
All class fields are accidentally declared public — they are accessed directly from other classes, making it difficult to track where changes occur.
Pros:
Cons:
All fields are private, and public methods control access with validation, while only necessary parts are made protected for extension in subclasses.
Pros:
Cons: