Definition
- Deprecated since Java 9\n- Not guaranteed to run\n- Delays GC by 2+ cycles\n- Replace with try-with-resources + Cleaner API
Understanding the Concepts
What is finalize() and why is it deprecated?
finalize() and why is it deprecated is an important concept in Java that every banking application developer should understand. In the context of National Bank of India's transaction processing system, Rajesh uses this concept regularly when building reliable financial services.
- Deprecated since Java 9\n- Not guaranteed to run\n- Delays GC by 2+ cycles\n- Replace with try-with-resources + Cleaner API
package com.bank.core;
import java.math.BigDecimal;
public class ConceptDemo {
private String accountId = "SAV2001";
private BigDecimal balance = new BigDecimal("50000.00");
public static void main(String[] args) {
ConceptDemo demo = new ConceptDemo();
System.out.println("Account: " + demo.accountId);
System.out.println("Balance: " + demo.balance);
}
}
Account: SAV2001
Balance: 50000.00
Why does finalize() and why is it deprecated matter?
Understanding finalize() and why is it deprecated is critical for building production-grade banking applications. Without this knowledge, developers may write code that behaves unexpectedly under load or fails in edge cases.
At National Bank of India, Pankaj emphasizes that every developer on the team must understand this concept because it directly affects the reliability and performance of the transaction processing pipeline.
- It affects how the JVM manages memory and resources.
- It influences the behavior of concurrent banking transactions.
- It determines how objects are created, stored, and cleaned up.
- It impacts application performance under high transaction volumes.
package com.bank.service;
import java.math.BigDecimal;
public class TransferService {
public boolean transfer(String fromAccount, String toAccount, BigDecimal amount) {
// This demonstrates why understanding the concept matters
BigDecimal fromBalance = getBalance(fromAccount);
if (fromBalance.compareTo(amount) >= 0) {
debit(fromAccount, amount);
credit(toAccount, amount);
System.out.println("Transferred " + amount + " from " + fromAccount + " to " + toAccount);
return true;
}
System.out.println("Insufficient balance in " + fromAccount);
return false;
}
private BigDecimal getBalance(String accountId) {
return new BigDecimal("100000.00");
}
private void debit(String accountId, BigDecimal amount) { /* debit logic */ }
private void credit(String accountId, BigDecimal amount) { /* credit logic */ }
}
How does finalize() and why is it deprecated work internally?
When the JVM processes this concept, it follows a specific internal mechanism. The JVM specification defines the behavior precisely, which ensures consistent results across different JVM implementations.
package com.bank.internal;
import java.math.BigDecimal;
public class InternalBehaviorDemo {
public static void main(String[] args) {
// Step 1: Object creation on the heap
BigDecimal balance = new BigDecimal("75000.00");
// Step 2: JVM processes the operation
BigDecimal interest = balance.multiply(new BigDecimal("0.045"));
// Step 3: Result is a new immutable object
System.out.println("Interest: " + interest);
System.out.println("Original unchanged: " + balance);
}
}
Interest: 3375.000
Original unchanged: 75000.00
How is this used in a banking application?
In National Bank of India's core banking system, Rajesh applies this concept in several places:
- Account processing: When creating and managing customer accounts.
- Transaction logging: When recording financial transactions for audit.
- Interest calculation: When computing daily interest on savings accounts.
- Statement generation: When building monthly statements for customers like Priya.
package com.bank.model;
import java.math.BigDecimal;
import java.time.LocalDateTime;
public class Transaction {
private final String transactionId;
private final String fromAccount;
private final String toAccount;
private final BigDecimal amount;
private final LocalDateTime timestamp;
public Transaction(String txnId, String from, String to, BigDecimal amount) {
this.transactionId = txnId;
this.fromAccount = from;
this.toAccount = to;
this.amount = amount;
this.timestamp = LocalDateTime.now();
}
@Override
public String toString() {
return "TXN[" + transactionId + "] " + fromAccount + " -> " + toAccount + " : " + amount;
}
public static void main(String[] args) {
Transaction txn = new Transaction("TXN-001", "SAV2001", "CUR3001", new BigDecimal("5000.00"));
System.out.println(txn);
}
}
TXN[TXN-001] SAV2001 -> CUR3001 : 5000.00
What are common mistakes?
A common mistake is not understanding the full implications of this concept in a banking production environment.
Wrong approach:
package com.bank.service;
public class WrongApproach {
public void processAccount() {
// WRONG: using double for money
double balance = 10000.50;
double fee = 0.1;
double result = balance - fee;
System.out.println(result); // 10000.4 (precision lost!)
}
}
Correct approach:
package com.bank.service;
import java.math.BigDecimal;
public class CorrectApproach {
public void processAccount() {
// CORRECT: using BigDecimal for money
BigDecimal balance = new BigDecimal("10000.50");
BigDecimal fee = new BigDecimal("0.10");
BigDecimal result = balance.subtract(fee);
System.out.println(result); // 10000.40 (exact!)
}
}
What should a senior engineer know?
A senior engineer should understand the production implications:
- Performance profiling: Use JFR (Java Flight Recorder) and JMC (Java Mission Control) to measure the impact in production.
- Thread safety: Consider how this concept interacts with concurrent access in a multi-threaded banking service.
- JVM tuning: Adjust JVM parameters based on the workload characteristics of the banking application.
- Monitoring: Set up JMX metrics and alerts in production to detect issues early.
package com.bank.monitoring;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
public class JvmInfoDemo {
public static void main(String[] args) {
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
System.out.println("JVM: " + runtime.getVmName());
System.out.println("Uptime: " + runtime.getUptime() + " ms");
System.out.println("Input args: " + runtime.getInputArguments());
}
}
What are the edge cases?
package com.bank.edge;
import java.math.BigDecimal;
public class EdgeCaseDemo {
public static void main(String[] args) {
// Edge case 1: null handling
String accountId = null;
System.out.println(accountId == null); // true
// Edge case 2: BigDecimal equality
BigDecimal a = new BigDecimal("10.0");
BigDecimal b = new BigDecimal("10.00");
System.out.println(a.equals(b)); // false (different scale)
System.out.println(a.compareTo(b) == 0); // true (same value)
// Edge case 3: Integer caching
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // true (cached)
Integer p = 128;
Integer q = 128;
System.out.println(p == q); // false (not cached)
}
}
true
false
true
true
false
What are common interview follow-up questions?
- How does this concept interact with garbage collection?
- What tools would you use to debug issues related to this concept?
- How does this behave differently in Java 8 vs Java 17+?
- What are the thread safety implications?
- How would you optimize this for a high-throughput banking system?
Key Takeaway
See Q110 (JVM Internals). finalize() is deprecated because it is unpredictable, delays GC, and has security issues. Use try-with-resources and Cleaner.\n\n
Remember one sentence: What is the role of finalize() in garbage collection, and why is it deprecated is fundamental knowledge for Java interviews and production banking work.
---