Interview questions

Finalise Java Interview: What It Means and What to Say Instead

August 15, 2025Updated May 15, 202616 min read
What Does Finalise Java Really Mean For Your Interview Success?

Master finalise Java interview answers: define finalize(), explain why JEP 421 discourages it, and say try-with-resources with AutoCloseable instead.

Most candidates freeze not because they don't know what `finalize()` does, but because they haven't thought through what to say after the definition. In a finalise Java interview question, the first sentence is easy — it's a method on `java.lang.Object` that the garbage collector calls before reclaiming an object. The second sentence is where answers fall apart, because the honest follow-up is that you shouldn't rely on it, and most candidates don't know how to say that confidently without sounding like they're avoiding the question.

This guide gives you the full picture: what `finalize()` actually is, why it's unreliable, what JEP 421 changed, and the exact replacement pattern — `try-with-resources` plus `AutoCloseable` — that you should lead with when the interviewer asks how cleanup should work in modern Java.

Why Interviewers Still Ask About finalize()

They Are Testing Whether You Know Old Java Without Being Trapped by It

The question persists in interview loops not because `finalize()` is a pattern teams still use, but because it's a useful filter. An interviewer asking about finalize in Java wants to know whether you understand the JVM's object lifecycle — and more importantly, whether you know when not to use something. Knowing that a feature exists is table stakes. Knowing that it's been deprecated for removal and why is what separates someone who has engaged with the language from someone who memorised a cheat sheet.

In practice, this question often appears as a follow-up to a broader discussion about garbage collection or resource management. It's rarely the primary design question — it's the secondary probe that checks whether the candidate is current.

What This Looks Like in Practice

The interviewer says: "What is `finalize()` in Java?"

A rote answer: "`finalize()` is a method called by the garbage collector before an object is destroyed."

That answer is technically correct and immediately forgettable. It tells the interviewer you read the docs. A stronger answer adds the modern caution in the same breath: "`finalize()` is a method on `Object` that the GC may call before reclaiming an instance — but because its timing is non-deterministic and it's deprecated for removal since Java 18, you wouldn't rely on it for real cleanup work."

That second version takes about five seconds longer to say and signals immediately that you're not trapped by legacy knowledge. Hiring discussions where this question comes up as a follow-up almost always use it as a quick credibility check — candidates who give only the definition and stop tend to get a harder follow-up; candidates who flag the deprecation voluntarily tend to move on faster.

The Java Platform documentation for `Object.finalize()` itself notes the method's limitations clearly, and that note has been there long enough that not mentioning it reads as a gap.

finalize() Is a GC Hook, Not a Cleanup Strategy

The Method Exists on Object, but the Timing Is the Problem

Every class in Java implicitly extends `java.lang.Object`, which means every class can override `finalize()`. The signature is `protected void finalize() throws Throwable`. When the garbage collector determines that no references to an object remain, it may call `finalize()` before reclaiming the memory. The word "may" is doing a lot of work in that sentence.

The finalize method in Java has no timing contract. The JVM can delay finalization indefinitely, batch it, or skip it entirely if the JVM exits. There's no guarantee that `finalize()` runs promptly after an object becomes unreachable, no guarantee it runs at all before the process ends, and no guarantee about which thread runs it. For anything that matters — file handles, database connections, sockets, locks — that's an unusable contract.

What This Looks Like in Practice

Consider this teaching example — shown only to illustrate why it's a bad pattern:

This looks reasonable at a glance. It closes the stream when the object is garbage collected. The problem is that "when the object is garbage collected" might mean five seconds from now, five minutes, or never in a long-running process. The file handle stays open the entire time. In a server application handling hundreds of requests, that delay compounds into resource exhaustion. Don't copy this pattern — it exists here only to show the failure mode.

The Java Language Specification on object finalization describes this non-deterministic behavior explicitly, and it's the reason the method has been on the deprecation path for years.

Stop Saying finalize() Is Reliable Just Because It Worked Once

The Old Argument Sounds Reasonable Until You Need Deterministic Cleanup

The classic defence of `finalize()` goes like this: it runs automatically, so you don't have to remember to close things. That's a real convenience, and in a simple test program that opens one file and exits, it probably does run. The problem is that "probably works in a test" is a terrible contract for production code.

The difference between `finalize()` and `finally` is instructive here — and this is one of the places where finalize vs finally confusion causes real interview damage. `finally` runs at a defined point: after the try block, before the method returns, regardless of whether an exception was thrown. That's deterministic. `finalize()` runs at a point determined by the GC, which is influenced by heap pressure, GC algorithm, JVM flags, and timing that your code has no visibility into. These are not two versions of the same idea — they're fundamentally different mechanisms.

What This Looks Like in Practice

The follow-up question "Is `finalize()` guaranteed to run?" is a direct trap. The correct answer is no. A JVM is permitted to exit without ever calling `finalize()` on any object. Even in a running JVM, finalization can be delayed until the heap is under pressure, which may be never in a well-tuned application with sufficient memory. More dangerously, if `finalize()` throws an unchecked exception, the exception is silently ignored — the object may be reclaimed without cleanup completing, and nothing in your logs will tell you.

A concrete example: imagine a database connection pool where connections are wrapped in objects that rely on `finalize()` to return connections to the pool. Under low GC pressure, the heap never fills, `finalize()` never runs, and the pool slowly starves. The application degrades hours after the bug was introduced, with no obvious stack trace pointing at the cause. This is the exact failure mode that makes delayed cleanup painful in production.

JEP 421, which proposed deprecating finalization for removal, cites reliability problems of exactly this kind as the primary motivation.

Use try-with-resources When the Resource Actually Matters

The Honest Replacement Is Boring, and That Is the Point

Java cleanup interview questions almost always have a second part: "So what should you use instead?" The answer is `try-with-resources`, and it's boring in the best possible way. It closes resources at the end of the block, at a predictable time, whether or not an exception was thrown. There's no GC involvement, no timing ambiguity, and no silent swallowing of exceptions.

The reason `try-with-resources` is the right answer in an interview is the same reason it's the right answer in production: it makes cleanup explicit and guaranteed. Deterministic cleanup is not a nice-to-have — it's the only kind of cleanup you can reason about.

What This Looks Like in Practice

The resource is opened in the parentheses after `try`, used in the block, and closed automatically when the block exits — even if an exception is thrown. No `finally` block needed. No `finalize()` override. The interviewer sees immediately that you know how modern Java handles this.

For a socket:

Same pattern. The interview takeaway is simple: this is deterministic cleanup, not hope-based cleanup.

Why AutoCloseable Is the Real Contract Behind the Pattern

`try-with-resources` works because the resource implements either `java.io.Closeable` or `java.lang.AutoCloseable`. `AutoCloseable` is the broader interface — it requires only a single `close()` method that throws `Exception`. When you write a user-defined type that wraps a resource, implementing `AutoCloseable` is what makes it eligible for `try-with-resources`.

Now `ConnectionWrapper` can be used directly in a `try-with-resources` block. The JVM has a clear, explicit close path instead of a GC-dependent guess. That's the contract the pattern is built on, and naming `AutoCloseable` in your interview answer shows you understand the mechanism, not just the syntax.

The Java Tutorials on try-with-resources cover this contract directly and are worth reading before any interview where resource management comes up.

Use Cleaner Only as a Fallback, Not Your First Answer

Cleaner Exists Because Some Cleanup Is Still Better Than Nothing

`java.lang.ref.Cleaner`, introduced in Java 9, is the modern replacement for `finalize()` when you genuinely need a last-resort safety net. It runs cleanup actions on phantom-reachable objects using a dedicated thread, without the unpredictability of the old finalizer queue. But the key word is safety net — `Cleaner` is for situations where explicit cleanup is the primary strategy and you want a backup in case something goes wrong, not a replacement for `try-with-resources`.

What This Looks Like in Practice

The explicit `close()` method is still there — `AutoCloseable` is still implemented — and `Cleaner` is registered as a fallback in case `close()` is never called. This is the correct layering: explicit cleanup first, `Cleaner` as a backup for memory-adjacent or native-resource scenarios.

`Cleaner` is not appropriate for closing database connections, releasing file locks, or anything where a delay of seconds or minutes would cause real problems. For those cases, `try-with-resources` is still the only safe answer. The Cleaner API documentation is explicit about this distinction.

Say What Changed With JEP 421 Without Sounding Like You Memorized a Blog Post

The Important Part Is the Direction, Not the History Lesson

JEP 421 — "Deprecate Finalization for Removal" — was targeted at Java 18 and proposed deprecating `Object.finalize()`, the `runFinalization()` methods, and related APIs with the intent of removing them in a future release. The title of the JEP is the interview point: for removal, not just discouraged. The trajectory is clear: finalize in Java is not a feature being maintained, it's a feature being retired.

You don't need to recite the JEP number in an interview. What you need to say is that finalization is on the removal path in modern Java, that the Java team has explicitly called it unreliable, and that the replacement direction is explicit cleanup through `AutoCloseable` and `try-with-resources`.

What This Looks Like in Practice

When asked about Java 18+ or modern Java cleanup, the short version is: "Finalization is deprecated for removal — it was always unreliable because of GC non-determinism, and JEP 421 formalised that by marking it for eventual removal. The modern approach is `try-with-resources` with `AutoCloseable`, and `Cleaner` for non-critical safety nets."

That answer is current, technically accurate, and shows you've engaged with where the language is going, not just where it's been. The JEP 421 announcement is public and worth reading once — the motivation section alone gives you the vocabulary to talk about this confidently.

Give the One-Sentence Interview Answer, Then Move On

The Answer Should Be Short Enough to Survive a Follow-Up

A model one-sentence answer: "`finalize()` is a protected method on `java.lang.Object` that the garbage collector may call before reclaiming an object, but because its timing is non-deterministic and it's deprecated for removal in modern Java, it's not a reliable cleanup mechanism."

That sentence defines the method, locates it on `Object`, ties it to GC, and flags the deprecation — all in one breath. It's short enough that the interviewer can follow up immediately, and it doesn't leave any obvious gaps for a gotcha.

What This Looks Like in Practice

The follow-up comparison — "What's the difference between `final`, `finally`, and `finalize()`?" — is one of the most common Java interview traps, and the finalize vs finally confusion is where candidates most often stumble.

Clean version:

  • `final` is a keyword. It makes a variable constant, a method non-overridable, or a class non-extendable.
  • `finally` is a block in exception handling. It runs after a `try` or `catch` block, guaranteed, whether or not an exception was thrown.
  • `finalize()` was a method on `Object` that the GC might call before reclaiming an instance. It's deprecated for removal and shouldn't be used for cleanup.

Three different mechanisms. One keyword, one exception-handling construct, one deprecated GC callback. Saying that cleanly and moving on is the right answer.

Common Mistakes That Make Candidates Sound Outdated

Confusing final, finally, and finalize() Is the Fastest Self-Own

The three terms look related because they share a root word. They are not related in any meaningful way. `final` is a modifier that restricts inheritance and mutation. `finally` is part of the exception-handling control flow. `finalize()` is a deprecated method tied to garbage collection. Treating them as a family of related concepts is the single most common mistake in finalize method Java questions, and it signals that the candidate learned the terms as a vocabulary list rather than as distinct mechanisms.

What This Looks Like in Practice

The interview trap is usually phrased as: "Can you explain the difference between `final`, `finally`, and `finalize()`?" The wrong answers sound like:

  • "`finalize()` is like `finally` but for objects" — no, they're unrelated.
  • "`finalize()` is guaranteed to run when the object is destroyed" — no, it's explicitly not guaranteed.
  • "`finalize()` is the recommended way to clean up resources" — this is the fastest way to sound out of date; it's been discouraged for years and formally deprecated since Java 18.
  • "You should override `finalize()` to close your streams" — this is what the Java team specifically warns against.

The exact wrong phrases tend to cluster around the word "guaranteed" and the word "recommended." Neither applies. The finalize method Java documentation has warned against relying on it for deterministic cleanup for over a decade, and JEP 421 made that official. Candidates who use either word in connection with `finalize()` give away immediately that their knowledge hasn't been updated.

A clean answer acknowledges that `finalize()` exists, describes what it was intended to do, and then pivots to why you'd use `try-with-resources` with `AutoCloseable` instead. That pivot is the whole interview.

---

Q: What is finalize() in Java in one interview-ready sentence?

`finalize()` is a protected method on `java.lang.Object` that the garbage collector may call before reclaiming an object, but because its execution timing is non-deterministic and it's deprecated for removal in modern Java, it's not a reliable mechanism for resource cleanup.

Q: How is finalize() different from final and finally?

`final` is a keyword that restricts modification — it makes variables constant, methods non-overridable, and classes non-extendable. `finally` is a control-flow block in exception handling that runs after a `try` block regardless of whether an exception occurred. `finalize()` was a GC callback method on `Object` — it's a deprecated cleanup hook, not a keyword and not related to exception handling.

Q: Is finalize() guaranteed to run when an object becomes unreachable?

No. The JVM is permitted to exit without calling `finalize()` on any object. Even in a running JVM, the GC may delay finalization indefinitely or skip it entirely. If `finalize()` throws an unchecked exception, the exception is silently ignored. There is no timing contract, no ordering guarantee, and no reliable way to verify it ran.

Q: Why is finalize() deprecated or discouraged in modern Java?

JEP 421 formalised what practitioners had known for years: finalization is unreliable, introduces performance overhead in the GC, creates security risks, and can't guarantee timely cleanup. The Java platform team deprecated it for removal in Java 18, signalling that the feature is being retired rather than maintained.

Q: What should you use instead of finalize() for cleanup and resource management?

Use `try-with-resources` with `AutoCloseable` for any resource that matters — file handles, connections, sockets. This gives you deterministic, guaranteed cleanup at a defined point in the code. If you need a last-resort safety net for non-critical cleanup, `java.lang.ref.Cleaner` is the modern alternative to `finalize()`, but it should back up explicit cleanup, not replace it.

Q: Can finalize() be overridden, and what is the correct method signature?

Yes. The signature is `protected void finalize() throws Throwable`. Since every class implicitly extends `java.lang.Object`, any class can override it. The convention when overriding was to call `super.finalize()` in a `finally` block to ensure the superclass cleanup ran. In practice, you should not override it in new code — implement `AutoCloseable` instead.

Q: What are the most common interview traps or misconceptions about finalize()?

Three come up repeatedly: saying it's "guaranteed to run" (it isn't), calling it "recommended for cleanup" (it's deprecated for removal), and conflating it with `finally` as though they're related constructs (they're not). A fourth trap is treating the three-way final/finally/finalize() comparison as a trivia question rather than a chance to show you understand what each mechanism actually does and when to use it.

How Verve AI Can Help You Ace Your Coding Interview With finalize()

The hardest part of a technical question like this isn't the definition — it's knowing when to stop reciting and start pivoting to the modern answer under live pressure. That pivot is a performance skill, not a recall skill, and it only improves with practice on realistic prompts.

Verve AI Coding Copilot is built for exactly this scenario. It reads your screen in real time during practice sessions and live rounds, surfacing the relevant context — deprecation status, replacement patterns, code examples — at the moment you need it, not after you've already given a shaky answer. For a question like `finalize()`, where the correct answer requires you to define the method, flag the deprecation, and name the replacement in one coherent response, having Verve AI Coding Copilot suggest answers live keeps you from freezing on the pivot. It works across LeetCode, HackerRank, CodeSignal, and live technical screens, and it stays invisible while it does — so you can focus on the conversation rather than the gap in your notes.

Conclusion

When the interviewer asks about `finalize()`, the goal is not to give a museum tour of old Java. The goal is to show that you know what the method was, why it was a problem, and what you'd use instead. That's a short answer: `finalize()` is a deprecated GC callback on `Object`, it's non-deterministic and unreliable, and modern Java cleanup means `try-with-resources` with `AutoCloseable` — with `Cleaner` as a fallback for non-critical safety nets only.

Lead with that, and the follow-up questions answer themselves.

JM

James Miller

Career Coach

Ace your live interviews with AI support!

Get Started For Free

Available on Mac, Windows and iPhone