W3docs

Java Non-Access Modifiers

Use Java's non-access modifiers — static, final, abstract, synchronized, transient, volatile — and what each controls.

Java's access modifiers — public, protected, private — control who can see a member. The non-access modifiers control how it behaves. They're a small grab-bag of keywords that change ownership, mutability, threading, serialization, and a few other things. This chapter is the map; each modifier has a fuller chapter or section elsewhere.

The full list

ModifierApplies toWhat it does
staticfields, methods, nested classes, blocksBelongs to the class, not to instances
finalclasses, methods, fields, parameters, localsCannot be reassigned/overridden/extended
abstractclasses, methodsNo body / cannot be instantiated; must be implemented by a subclass
synchronizedmethods, blocksOnly one thread at a time may execute it on a given lock
volatilefieldsReads/writes are not cached in thread-local memory
transientfieldsSkipped by default serialization
nativemethodsImplementation lives in non-Java code (usually C/C++)
strictfpclasses, methodsForces strict IEEE-754 float behavior (largely historical)
defaultinterface methodsProvides a default body in an interface
sealed / non-sealedclasses, interfacesRestricts which classes may extend (Java 17+)

You'll meet static, final, abstract, and default constantly. The rest you'll see only when their problem comes up.

static — belongs to the class

A static member is associated with the class itself, not with any single instance:

public class Counter {
  int instanceCount;          // one per Counter object
  static int classCount;      // one shared by everyone
}

static is so common it gets its own chapter — see java-static.

final — cannot change

final means "this binding is fixed after it's set." It applies to a few different things:

final int MAX = 100;          // local variable cannot be reassigned
public final class Money {}   // class cannot be extended
public final void close() {}  // method cannot be overridden
private final int balance;    // field assigned once, then immutable

final is the foundation of constants (static final), immutable objects, and safe inheritance design. Full treatment in java-final.

abstract — has no body, must be filled in

abstract applied to a class means "you can't instantiate this directly — only subclasses." Applied to a method, it means "no body here — every concrete subclass must provide one":

public abstract class Shape {
  public abstract double area();      // no body
}

public class Circle extends Shape {
  double r;
  public double area() { return Math.PI * r * r; }
}

new Shape() is a compile error; new Circle() works. Covered in abstract classes.

synchronized — one thread at a time

When two threads might call the same method on the same object, marking the method synchronized makes sure only one runs at a time:

public synchronized void deposit(int amount) {
  balance += amount;
}

This is the simplest form of locking. There's an entire concurrency chapter later in the book; for now, recognize that the keyword exists and what it broadly does.

volatile — visible across threads

Without volatile, threads are allowed to cache a field's value. Reads in one thread might never see writes from another:

private volatile boolean stopped = false;

volatile forces every read to come from main memory and every write to go to main memory. It's the lightweight cousin of synchronized for simple flag fields.

transient — skip on serialization

Java's built-in object serialization (Serializable) writes every field by default. transient says "don't include this one" — typically used for caches, computed values, or things that don't make sense outside the running program:

public class Session {
  String userId;
  transient String passwordHash;     // not serialized
}

Modern code uses JSON serializers more than Serializable, but the keyword is still useful in libraries that care about it.

native — implemented elsewhere

native is for methods whose body is in another language (C/C++ via JNI). You rarely write them yourself; you only see them in low-level libraries:

public native int currentTimeMillis();

strictfp — strict floating-point

Originally, strictfp forced predictable IEEE-754 float arithmetic across platforms. As of Java 17, all floating-point math is implicitly strict, which makes the keyword a no-op. You can mostly ignore it; it lingers in older codebases.

default — on interface methods

Inside an interface, default lets you provide a body for a method instead of leaving it abstract:

public interface Greeter {
  default String greet(String name) {
    return "Hello, " + name;
  }
}

Without default, an interface method has no body and every implementing class has to write its own. Full treatment in default methods.

sealed and non-sealed

A sealed class names the exact list of classes allowed to extend it. Subclasses must then choose to be final, sealed, or non-sealed:

public sealed class Shape permits Circle, Square { }
public final class Circle extends Shape { }
public non-sealed class Square extends Shape { }

Useful for closed type hierarchies — see sealed classes.

Combining modifiers

You can usually stack modifiers freely, in this conventional order:

public  static  final   int MAX = 100;
private static  volatile int counter;
protected abstract       void onInit();

Some combinations are illegal: a method can't be both abstract and final, both abstract and private, or both abstract and static. The compiler will tell you when you've crossed a line.

A worked example

java— editable, runs on the server

What's next

The next two chapters drill into the two modifiers you'll use most often: static for class-level members, then final for immutability. Read them in order.

Practice

Practice

Which non-access modifier means a class member belongs to the class itself rather than to each instance?