Modifiers – File Level, Access Level and Non-Access Level

Java 10 min min read Updated: Mar 30, 2026 Beginner
Modifiers – File Level, Access Level and Non-Access Level
Beginner Topic 6 of 25

Modifiers – File Level, Access Level and Non-Access Level

In Java, modifiers are special keywords used to define the behavior, visibility, and restrictions of classes, methods, variables, constructors, and blocks. Modifiers tell the compiler and other programmers how a particular program element can be accessed and how it should behave.

Without modifiers, Java code would become difficult to control because there would be no clear rule about which class, method, or variable should be visible outside a class, whether a method can be overridden, whether a class can be inherited, or whether a variable can be changed.

Key Concept: Modifiers are keywords that define the visibility and behavior of classes, methods, variables, and constructors. In Java, modifiers are commonly grouped as file-level, access-level, and non-access-level modifiers.

What are Modifiers in Java?

Modifiers are predefined keywords that are placed before class, method, variable, or constructor declarations to control their usage.

Example:

java public class Student { private int age; public void show() { System.out.println(age); } }

In the above code:

  • public is a modifier
  • private is a modifier

These modifiers control who can access the class, variable, or method.

Categories of Modifiers in Java

Modifiers in Java are commonly discussed under these categories:

  • File-level modifiers
  • Access-level modifiers
  • Non-access modifiers

Let us understand each one in detail.

1. File-Level Modifiers

File-level modifiers are those modifiers that are used with top-level classes and interfaces. In Java, a file can contain multiple classes, but only one top-level class can be declared as public.

For top-level classes and interfaces, only two modifiers are meaningful:

  • public
  • default (no modifier)

This means top-level classes cannot be declared as:

  • private
  • protected

because these modifiers do not make sense at file level.

Public Top-Level Class

If a class is declared as public, it can be accessed from any package.

java public class Demo { public static void main(String[] args) { System.out.println("Public class example"); } }

Important rule:

  • If a class is public, the file name must match the class name exactly.

So the above class must be saved in:

text Demo.java

Default Top-Level Class

If no modifier is written, the class gets default access. This means it can only be accessed within the same package.

java class Sample { void show() { System.out.println("Default class example"); } }

This class cannot be used directly from another package.

Why Private and Protected are Not Allowed for Top-Level Classes

A top-level class exists at package level. Since private means “accessible only within the same class” and protected means “accessible within the package and subclasses,” neither is suitable for a top-level class.

Therefore, Java allows only:

  • public
  • default

Invalid Example

java private class Test { } // Invalid protected class Demo { } // Invalid

The compiler will throw an error for both.

2. Access-Level Modifiers

Access-level modifiers define how broadly a class member can be accessed. They are mainly used with:

  • variables
  • methods
  • constructors
  • inner classes

Java provides four access levels:

  • private
  • default (no modifier)
  • protected
  • public

1. Private Modifier

private is the most restrictive access modifier. A private member can only be accessed within the same class.

java class Student { private int age = 20; public void showAge() { System.out.println(age); } }

Here, age cannot be accessed directly outside the Student class.

Example

java public class Main { public static void main(String[] args) { Student s = new Student(); // System.out.println(s.age); // Error s.showAge(); } }

Output

text 20

Private is commonly used in encapsulation to protect data.

2. Default Access Modifier

If no access modifier is written, Java provides default access, also called package-private access.

A default member can be accessed only within the same package.

java class Student { int marks = 90; // default access }

This variable can be accessed by other classes in the same package, but not from another package.

3. Protected Modifier

protected allows access:

  • within the same package
  • outside the package through inheritance

This modifier is mainly useful in inheritance.

java class Animal { protected void eat() { System.out.println("Animal is eating"); } }

A subclass in another package can access the protected method through inheritance.

4. Public Modifier

public is the least restrictive access modifier. A public member can be accessed from anywhere.

java public class Student { public void display() { System.out.println("Public method"); } }

Any class in any package can access this public method.

Access Modifier Comparison Table

Modifier Same Class Same Package Subclass in Another Package Other Package
private Yes No No No
default Yes Yes No No
protected Yes Yes Yes No
public Yes Yes Yes Yes
Memory Tip: Access control goes from most restrictive to least restrictive as: private → default → protected → public.

3. Non-Access Modifiers

Non-access modifiers do not mainly control visibility. Instead, they define special behavior or restrictions on classes, methods, variables, and blocks.

Important non-access modifiers in Java include:

  • static
  • final
  • abstract
  • synchronized
  • transient
  • volatile
  • native
  • strictfp

Let us understand the major ones in detail.

Static Modifier

The static modifier means that a member belongs to the class rather than to any specific object.

Static Variable

A static variable is shared among all objects of the class.

java class Student { static String college = "ABC College"; String name; Student(String name) { this.name = name; } void show() { System.out.println(name + " - " + college); } }
java public class Main { public static void main(String[] args) { Student s1 = new Student("Amit"); Student s2 = new Student("Riya"); s1.show(); s2.show(); } }

Output

text Amit - ABC College Riya - ABC College

Static Method

A static method can be called without creating an object.

java class Demo { static void show() { System.out.println("Static method"); } }
java public class Main { public static void main(String[] args) { Demo.show(); } }

Final Modifier

The final modifier is used to restrict modification.

Final Variable

A final variable cannot be reassigned once initialized.

java class Demo { final int x = 100; void show() { System.out.println(x); } }

Trying to change x later will cause a compile-time error.

Final Method

A final method cannot be overridden by a child class.

java class Parent { final void display() { System.out.println("Final method"); } }

Final Class

A final class cannot be inherited.

java final class Vehicle { }

The String class is a famous example of a final class.

Abstract Modifier

The abstract modifier is used with classes and methods when incomplete behavior is intentionally defined and must be completed by subclasses.

Abstract Class

An abstract class cannot be instantiated directly.

java abstract class Animal { abstract void sound(); }

Abstract Method

An abstract method has no body and must be implemented by child classes.

java class Dog extends Animal { void sound() { System.out.println("Dog barks"); } }

Synchronized Modifier

The synchronized modifier is used in multithreading to control access to a method by only one thread at a time.

java class Counter { synchronized void increment() { System.out.println("Counter updated safely"); } }

This is important in concurrent programming where multiple threads may try to access shared resources.

Transient Modifier

The transient modifier is used in serialization. A transient variable is not saved when an object is serialized.

java class Student { transient int tempData; }

Volatile Modifier

The volatile modifier tells Java that the value of a variable may be changed by multiple threads, so it should always be read from main memory.

java class Demo { volatile boolean flag = true; }

Native Modifier

The native modifier is used for methods whose implementation is written in another language such as C or C++.

java class Demo { native void show(); }

Strictfp Modifier

The strictfp modifier ensures consistent floating-point calculations across different platforms.

java strictfp class Demo { double value = 10.5; }

Where Modifiers Can Be Used

Modifier Class Method Variable Constructor
public Yes Yes Yes Yes
private No (top-level) Yes Yes Yes
protected No (top-level) Yes Yes Yes
static No (top-level class) Yes Yes No
final Yes Yes Yes No
abstract Yes Yes No No

Modifier Combination Rules

Some modifiers can be combined, while some cannot.

Valid Example

java public final class Demo { }

This means the class is accessible everywhere and cannot be inherited.

Invalid Example

java abstract final class Test { }

This is invalid because:

  • abstract means class must be inherited
  • final means class cannot be inherited

Both ideas conflict with each other.

Real-World Example Combining Modifiers

Let us see a practical class where multiple modifiers are used together.

java public class BankAccount { private String accountHolder; private double balance; public static final String BANK_NAME = "ABC Bank"; public BankAccount(String accountHolder, double balance) { this.accountHolder = accountHolder; this.balance = balance; } public void deposit(double amount) { balance += amount; } public void showDetails() { System.out.println(accountHolder + " - " + balance + " - " + BANK_NAME); } }

In this class:

  • public makes the class accessible everywhere
  • private protects internal data
  • static final is used for a constant shared by all objects

Common Mistakes with Modifiers

  • Using private or protected with top-level classes
  • Trying to override a final method
  • Trying to instantiate an abstract class directly
  • Thinking default access means public access
  • Using static where instance behavior is required

Best Practices

  • Use private for data hiding and encapsulation
  • Use public only when broad access is really needed
  • Use protected mainly in inheritance-related designs
  • Use final for constants and restricted behavior
  • Use abstract when defining incomplete base classes
  • Choose modifiers carefully to keep code secure and maintainable

Interview-Oriented Points

  • Top-level classes can only be public or default
  • Access modifiers are private, default, protected, and public
  • Non-access modifiers define behavior rather than visibility
  • final restricts change, abstract defines incomplete behavior
  • static means class-level, not object-level
  • private is most restrictive, public is least restrictive
  • abstract final is invalid because the modifiers conflict

Conclusion

Modifiers are one of the most important parts of Java syntax because they define how classes and members behave and how they are accessed. Without modifiers, Java programs would have weak structure, poor encapsulation, and less control over inheritance and data security.

Understanding file-level, access-level, and non-access-level modifiers helps build strong foundations for object-oriented design, class relationships, and safe coding practices.

Quick Summary: File-level modifiers control top-level class visibility, access-level modifiers control who can access members, and non-access modifiers define special behavior such as class-level sharing, restriction, abstraction, and thread safety.

Get Newsletter

Subscibe to our newsletter and we will notify you about the newest updates on Edugators