skip to content

final Classes & Methods

final on a class blocks subclassing and on a method blocks overriding, which is how you express and enforce design intent. Interviewers ask about it when discussing immutability, security-sensitive classes, and why String is final.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

4

What does the `final` keyword do when applied to a class versus a method in Java?

level: juniorimportance: must knowfreq 70%

answer

  1. final class = no subclass (e.g. String)
  2. final method = no override, but class still extensible
  3. compile-time error, enforced by javac
  4. class lock is strongest; method lock is targeted
  5. separate meaning from final variable/field

basics

~20 s

A final class can't be extended (no subclasses). A final method can't be overridden by a subclass, though the class itself can still be subclassed. Both lock down a piece of behavior so others can't change it.

solid answer

~40 s

`final` on a class means it cannot be subclassed at all — `class Sub extends FinalClass` is a compile error. `String`, `Integer`, and the other wrapper types are classic examples. `final` on a method means subclasses cannot override that specific method, but they can still extend the class and override its non-final methods. So a final class is the stronger lock (no inheritance whatsoever), while a final method is a targeted lock on one piece of behavior within an otherwise extensible class. Both are compile-time enforced. The keyword expresses design intent — "I did not design this to be changed via inheritance" — and is checked by `javac`, not at runtime. Note `final` also applies to variables/fields (preventing reassignment), which is a separate, unrelated meaning of the same keyword.

code

java · 16 lines
java
public final class Money {        // no subclass allowed
    private final long cents;       // (different 'final': no reassignment)
    public Money(long cents) { this.cents = cents; }
}

public class Account {
    public final void audit() {}    // subclasses can't override this
    public void describe() {}        // subclasses MAY override this
}

// class Wallet extends Money {}   // COMPILE ERROR: Money is final

class Savings extends Account {
    // void audit() {}              // COMPILE ERROR: audit() is final
    @Override public void describe() {} // OK: describe() is not final
}

go deeper

for a junior

Knows final class = can't extend, final method = can't override, and that String is final. Can state it's a compile error.

for a middle

Distinguishes the strength of the two locks, names JDK examples, and separates final-class/method from final-variable. Knows overloading still works.

for a senior

Frames final as design intent enforced at compile time, connects final methods to template-method skeletons, and reasons about extensibility trade-offs.

for a principal

Discusses sealing strategy across an API surface (final vs sealed vs package-private constructors), migration/back-compat implications of removing final, and JIT devirtualization benefits.

## Background: what inheritance and overriding mean In Java, **inheritance** lets one class (a *subclass*) be declared with `class B extends A {}`, so `B` automatically gains `A`'s fields and methods. **Overriding** is when the subclass supplies its own implementation of a method that the parent already defined — same name, same parameters — so calling that method on a `B` object runs `B`'s version even through a variable typed as `A`. This is the engine of *polymorphism* (one reference type, many runtime behaviors). The `final` keyword is a modifier that *removes* one of these capabilities, depending on where you put it. ## `final` on a class ```java public final class Money { ... } ``` This says: **no class may extend `Money`.** Any attempt — `class Wallet extends Money` — is a **compile-time error** ("cannot inherit from final Money"). There are no subclasses, ever. Real-world final classes in the JDK include `String`, `Integer`, `Long`, `Double` (all the wrapper types), `LocalDate`, and `Optional`. Because a final class can't be subclassed, none of its methods can be overridden either (there's no subclass to override them in). So `final class` is the *strongest* lock: it forbids inheritance entirely. ## `final` on a method ```java public class Account { public final void recordAudit() { ... } // cannot be overridden public void describe() { ... } // can be overridden } ``` This is a *narrower* lock. The class `Account` is still extensible — subclasses are allowed. But within any subclass, `recordAudit()` **cannot be overridden**; `class Savings extends Account { void recordAudit(){} }` is a compile error. Meanwhile `describe()`, which is *not* final, can be overridden freely. So a final method pins down one specific behavior while leaving the rest of the class open. ## Why these are different tools - **Final class** = "this whole type is sealed; extend it through composition, not inheritance." - **Final method** = "extend me if you like, but *this* method's contract is non-negotiable — you may not swap its behavior." A common pattern is a non-final class with a final *template method* that calls overridable *hook methods*: the skeleton (the final method) is fixed, the steps (non-final methods) are customizable. ## Enforcement and scope All of this is enforced by the compiler (`javac`) at compile time, not by the JVM at runtime — it's about what code is *legal to write*. `final` is also unrelated to `final` on a **variable or field**, which instead means "this reference/value cannot be reassigned after initialization." Same keyword, three distinct meanings: final class (no subclass), final method (no override), final variable (no reassignment). ## How to derive the answer Ask "what does inheritance let someone do?" → create subclasses and override methods. `final` selectively forbids those: on a class it forbids *subclassing* (and therefore all overriding); on a method it forbids *overriding that one method* while still allowing subclassing.

  • Can you override a final method by overloading it (same name, different parameters)?
    Yes — overloading creates a different method signature, which `final` does not block. `final` only prevents *overriding* (same name and parameter list). A subclass may declare `recordAudit(String reason)` even if `recordAudit()` is final.
  • If a class is final, is there any point in also marking its methods final?
    No — a final class can have no subclasses, so its methods can never be overridden regardless. Marking them final is redundant (and some style checkers flag it).

saying these in an interview costs you the question

  • Saying a final method also prevents subclassing the class — it doesn't, only the method can't be overridden
  • Confusing final (no override/subclass) with final on a variable (no reassignment)
  • Claiming final is a runtime check — it's enforced at compile time
  • Saying a final method can't be overloaded — it can; final blocks overriding, not overloading

context

open as a page

When should you choose to make a class or method `final` as a design decision, and what are the trade-offs?

level: middleimportance: should knowfreq 50%

basics

~20 s

Make a class or method final when it isn't designed to be extended or changed — like value/immutable types or a security-critical method. The trade-off is lost flexibility: others can't subclass or override it, and some testing/mocking tools struggle with final.

open as a page

Why is the `final` keyword important for security and immutability, and why is `java.lang.String` final?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Marking a class final stops anyone from subclassing it to inject malicious or behavior-changing code. String is final so an attacker can't subclass it to make a "string" whose value secretly changes after a security check, which keeps it safely immutable.

open as a page

How does making a method `final` interact with the template-method pattern and JIT optimization, and what subtle pitfalls exist when finalizing methods in an inheritable class?

level: principalimportance: nice to knowfreq 28%

basics

~20 s

A final method is perfect for the fixed skeleton in the template-method pattern: the algorithm stays locked while subclasses fill in the open hook methods. Final methods also help the JIT inline calls since there's only one implementation. Pitfalls: a constructor calling an overridable method, and accidentally locking behavior subclasses legitimately need.

open as a page