Java Access and Non-Access Modifiers

Java modifiers answer two questions: who may access a member, and what special rules govern its behavior? Access modifiers control visibility.

Lesson 39 of 127Intermediate14 min read

Java modifiers answer two questions: who may access a member, and what special rules govern its behavior? Access modifiers control visibility. Non-access modifiers such as static, final and abstract describe ownership or implementation restrictions. Combining them correctly makes a class easier to use safely.

Review the related foundation lesson when you need a prerequisite. The complete programs below use Java 17-compatible syntax.

Access levels

public, protected, package access and private control where declarations can be accessed. Package access is expressed by omitting an access modifier.

public permits access wherever the declaring type is accessible; private restricts access to the enclosing top-level class and its nested members. With no access keyword, a member has package access. protected permits package access and subclass access, but cross-package subclass access has additional receiver restrictions. It is therefore inaccurate to describe protected as simply public to every subclass object everywhere.

Visibility for members and nested types

private members are for implementation details. protected also has subclass rules, especially across packages; it does not simply mean public to every subclass reference.

A top-level class can be public or have package access; private and protected apply to appropriate members or nested types, not ordinary top-level class declarations. A public type in a conventional source file must match that file's name. Start with the smallest useful visibility. Increasing visibility later is usually easier than withdrawing a public method that other code has already adopted.

Static and final behavior

static associates a member with its class. final prevents reassignment, overriding or inheritance depending on whether it applies to a variable, method or class.

static attaches a field or method to the class rather than an instance. final prevents reassignment of a variable, overriding of a method or extension of a class, depending on placement. A final list reference still permits changes to the list's contents. Constants commonly combine public, static and final, but the value should be immutable when callers are allowed to share it freely.

Abstract and specialized modifiers

abstract describes an incomplete class or method contract. Other modifiers such as synchronized, volatile and transient address particular runtime or storage concerns rather than visibility.

abstract says that a class cannot be instantiated directly or that a method requires an implementation in a concrete subclass. An abstract method cannot also be final, because one requires overriding while the other forbids it. synchronized coordinates monitor access; volatile supports visibility for a field but does not make a compound increment atomic. These words express different contracts, not interchangeable levels of safety.

Running the examples

Save name.java, compile it with javac --release 17 name.java, and run java name. Use each program's own public class name and filename.

How PermitModifiers produces its output

The example separates the shared immutable label from data owned by an individual object. Reading a static constant through the class name makes that ownership visible. The private field is accessed through a method rather than by an unrestricted external assignment, so later validation can remain inside the class.

How FinalListReference produces its output

final prevents names from being assigned another list after initialization. It does not freeze the ArrayList object that names refers to. Both add calls are legal and the list contains two entries. To forbid modifications to contents, use an unmodifiable collection or a genuinely immutable value design rather than relying on the reference modifier.

How LabelVisibility produces its output

UNIT is one class constant and is reached through LabelVisibility. count is an instance field with the numeric default zero. The public count method exposes a read operation without exposing a public writeable field. The nested code in the declaring class can access its private members, but unrelated callers should use the published method.

Read combined modifiers as separate promises

private final int id means access is restricted and the field may be assigned only through its permitted initialization. Neither word makes the field static. public static final String LABEL makes one published class value whose reference cannot be reassigned. The String itself is immutable, so that combination is suitable for a shared label. Contrast it with public static final ArrayList<String>: the reference is fixed but callers can still add elements. In practice, first choose visibility, then decide whether ownership is per object or per class, then choose reassignment restrictions. Reading each modifier independently prevents treating a long declaration as a single vague safety setting.

Java Summary

  • public, protected, package access and private control where declarations can be accessed. Package access is expressed by omitting an access modifier.
  • private members are for implementation details. protected also has subclass rules, especially across packages; it does not simply mean public to every subclass reference.
  • static associates a member with its class. final prevents reassignment, overriding or inheritance depending on whether it applies to a variable, method or class.
  • abstract describes an incomplete class or method contract. Other modifiers such as synchronized, volatile and transient address particular runtime or storage concerns rather than visibility.
  • Continue with Java exercises, Java quizzes and the Java study roadmap.

Java Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Java Access and Non-Access Modifiers in a complete program

Java
public class PermitModifiers  {
    static final class Permit  {
        static final String PREFIX = "Permit ";
        private final String id;
        Permit(String id)  {
            this.id=id;
        }
        String number()  {
            return id;
        }
    }
    public static void main(String[] args)  {
        Permit permit = new Permit("P-42");
        System.out.println(Permit.PREFIX + permit.number());
    }
}
Output
Permit P-42
Line-by-line explanation
  1. Line 14Evaluates Permit.PREFIX + permit.number() and prints Permit P-42.
Example 2

Final reference, mutable contents

Java
public class FinalListReference  {
    public static void main(String[] args)  {
        final java.util.List<String> names = new java.util.ArrayList<>();
        names.add("Mira");
        names.add("Jon");
        System.out.println(names.size());
    }
}
Output
2
Line-by-line explanation
  1. Line 6Evaluates names.size() and prints 2.
Example 3

Shared constant and instance state

Java
public class LabelVisibility  {
    public static final String UNIT = "pages";
    private int count;
    public int count()  {
        return count;
    }
    public static void main(String[] args)  {
        LabelVisibility item = new LabelVisibility();
        System.out.println(LabelVisibility.UNIT);
        System.out.println(item.count());
    }
}
Output
pages
0
Line-by-line explanation
  1. Line 9Evaluates LabelVisibility.UNIT and prints pages.
  2. Line 10Evaluates item.count() and prints 0.

Java FAQ

Does protected mean public?

No. It includes package access and restricted subclass access. In a different package, a subclass cannot use an arbitrary superclass instance to reach a protected instance member just because it extends that class. Check the receiver and the declaring package.

Can final make an object immutable?

A final field cannot be reassigned after its allowed initialization, but any referenced mutable object may still change. Immutability also requires controlling those objects, preventing unintended setters and avoiding leaked mutable internal references.

What is the default access level in Java?

If you write no access modifier, a class or member has package access, often called package-private: any class in the same package can use it, and classes in other packages can't. It sits between private and protected in how widely it can be reached.

In what order should modifiers be written?

Java accepts any order, but the convention follows the language specification: access first, then abstract, static, final, transient, volatile and synchronized. So write public static final int MAX = 10; and private static final, which is what code reviewers and tools expect to see.

Can a top-level class be private or protected?

No. A top-level class can only be public or have package access. private, protected and static are allowed on nested classes, where they control access from the enclosing class and the rest of the program.

Java Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Multiple choiceeasy

Which modifier prevents a method from being overridden?

Multiple choicemedium

Why can final List values still accept add?

Java Quiz

2 questions to check what you learned.

  1. Which access level is used when a member has no access keyword?

    • Package access
    • public
    • protected
  2. Can an ordinary top-level class be private?

    • No, it can be public or have package access
    • Yes, if main is public
    • Yes, if it is final