Definition
final restricts what you can do to the variable, not what you can do with the value:
- You CAN read a final variable. Reading does not modify it.
- You CAN assign its value to another variable.
int b = a;copies the value. - You CANNOT reassign the final variable.
a = 30;does not compile.
A sealed envelope in the bank vault. You can photocopy the document inside (read the value). You can give the photocopy to someone else (assign to another variable). You cannot replace the document inside the envelope (reassign).
Understanding the Concepts
Can you assign a final variable's value to another variable?
final int a = 20;
int b = a; // OK: copies the VALUE 20 into b
int c = a + 10; // OK: reads a, computes 30, stores in c
System.out.println(a); // 20 (unchanged)
System.out.println(b); // 20
System.out.println(c); // 30
b = 50; // OK: b is not final, can be reassigned
// a = 50; // COMPILE ERROR: a is final
Reading a final variable and assigning its value to another variable is always legal. final only prevents reassignment of the final variable itself.
What about reference types?
final Account a = new Account("SAV2001", new BigDecimal("1000000"));
Account b = a; // OK: b now points to the SAME object as a
System.out.println(a == b); // true (same object)
b.debit(new BigDecimal("50000")); // modifies the shared object
System.out.println(a.getBalance()); // 950000 (a sees the change too!)
// a = new Account("CUR3001", BigDecimal.ZERO); // COMPILE ERROR: a is final
b = new Account("CUR3001", BigDecimal.ZERO); // OK: b is not final
For reference types, Account b = a copies the reference (both point to the same object), not the object itself. Modifying the object through b is visible through a.
Why does this question appear in interviews?
Interviewers test whether you confuse "cannot reassign" with "cannot read." Many candidates wrongly think final means "locked in every way." It does not. final only prevents reassignment (a = newValue). Reading, passing, copying, and using the value in expressions are all allowed.
What should a senior engineer know?
- final primitives are compile-time constants when initialized with a literal. The compiler inlines the value:
final int MAX = 100;can be used in switch cases and annotation values. - final references are not inlined.
final Account a = new Account(...)is not a compile-time constant because the object is created at runtime.
What are common mistakes?
A common mistake is not understanding the concept fully before using it in production banking applications.
Wrong approach:
package com.bank.service;
public class TransferService {
public void transfer(String fromAccount, String toAccount, double amount) {
// WRONG: using double for money
double balance = getBalance(fromAccount);
balance = balance - amount;
}
private double getBalance(String id) { return 10000.0; }
}
Correct approach:
package com.bank.service;
import java.math.BigDecimal;
public class TransferService {
public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
// CORRECT: using BigDecimal for money
BigDecimal balance = getBalance(fromAccount);
balance = balance.subtract(amount);
}
private BigDecimal getBalance(String id) { return new BigDecimal("10000.00"); }
}
Always use BigDecimal for monetary calculations in banking systems to avoid floating-point precision errors.
What are the edge cases?
Edge cases can cause unexpected behavior in banking applications. Here are some to watch for.
package com.bank.edge;
public class EdgeCaseDemo {
public static void main(String[] args) {
// Edge case 1: null handling
String accountId = null;
try {
System.out.println(accountId.length());
} catch (NullPointerException e) {
System.out.println("Null account ID");
}
// Edge case 2: empty vs null
String emptyId = "";
System.out.println(emptyId.isEmpty()); // true
System.out.println(emptyId == null); // false
// Edge case 3: boundary values
java.math.BigDecimal zero = java.math.BigDecimal.ZERO;
java.math.BigDecimal negativeBalance = new java.math.BigDecimal("-0.01");
System.out.println(zero.compareTo(negativeBalance) > 0); // true
}
}
Null account ID
true
false
true
Always test with null values, empty strings, boundary values, and negative amounts in banking applications.
What are common interview follow-up questions?
Interviewers often follow up with these related questions:
- How does this concept apply to a high-throughput banking transaction system?
- What are the performance implications in a production environment?
- How would you debug issues related to this concept?
- What tools would you use to monitor this in production?
- How does this behave differently in Java 8 vs Java 17+?
When answering follow-up questions, always relate your answer back to practical experience. For example, at National Bank of India, Rajesh debugged a production issue related to this concept by using JFR recordings and heap dumps. Providing concrete examples from banking systems shows the interviewer that you understand both the theory and the practice.
Visual Overview
final int a = 20; int b = a; ← OK: copies value 20 into b int c = a + 10; ← OK: reads a, computes 30 // a = 30; ← COMPILE ERROR: cannot reassign final b = 50; ← OK: b is not final // a still 20, b is now 50 final Account x = new Account(...); Account y = x; ← OK: y points to same object y.debit(500); ← OK: modifies the shared object // x = new ... ← COMPILE ERROR: x is final
Key Takeaway
Yes, you can assign a final variable's value to another variable. final prevents reassignment of the variable itself, not reading its value. int b = a copies the value 20 into b. Changing b does not affect a. For reference types, both variables point to the same object, so changes through one are visible through the other.
One sentence to remember: final means you cannot reassign the variable – you can always read it, copy it, and use it in expressions.
---