final — keyword that prevents modification. finally — block that always runs after try/catch. finalize() — deprecated method called before garbage collection.
Analogy: final is like a sealed envelope — once sealed, you can't change what's inside. finally is like the janitor who always cleans up after an event, no matter how the event ended. finalize() is like a building inspector who used to check buildings before demolition, but the process was too unreliable and has been replaced.
final keyword (3 uses):
1final int MAX_SIZE = 100;2// MAX_SIZE = 200; // COMPILE ERROR34// Final reference: reference can't change, but object can5final List<String> list = new ArrayList<>();6list.add("item"); // OK — modifying object contents7// list = new ArrayList<>(); // COMPILE ERROR — can't reassign89// Final in constructor/initializer pattern10class Config {11 final String databaseUrl;1213 Config(String url) {14 this.databaseUrl = url; // Must be set exactly once15 }16}
1class PaymentProcessor {2 final void validatePayment(double amount) {3 if (amount <= 0) throw new IllegalArgumentException("Amount must be positive");4 }5}67class CreditCardProcessor extends PaymentProcessor {8 // void validatePayment(double amount) { } // COMPILE ERROR: can't override final9}
1final class ImmutablePoint {2 private final int x;3 private final int y;45 public ImmutablePoint(int x, int y) {6 this.x = x;7 this.y = y;8 }9 // No setters — truly immutable10}11// String, Integer, Math are all final classes in Java
finally block:
1Connection conn = null;2try {3 conn = dataSource.getConnection();4 // execute queries...5 return result; // finally STILL runs before this return!6} catch (SQLException e) {7 System.err.println("Database error: " + e.getMessage());8 throw e; // Re-throw after finally9} finally {10 // Always clean up11 if (conn != null) {12 try {13 conn.close();14 } catch (SQLException e) {15 System.err.println("Error closing connection");16 }17 }18 System.out.println("Cleanup complete");19}2021// Modern: try-with-resources (no finally needed)22try (Connection conn2 = dataSource.getConnection();23 Statement stmt = conn2.createStatement()) {24 ResultSet rs = stmt.executeQuery("SELECT * FROM users");25 // process results...26} catch (SQLException e) {27 System.err.println("Error: " + e.getMessage());28}29// conn2 and stmt closed automatically — cleaner than finally
finalize() method (DEPRECATED since Java 9):
protected void finalize() throws Throwable { } — inherited from Object.1// OLD, BAD approach:2class OldResource {3 @Override4 protected void finalize() throws Throwable {5 try {6 System.out.println("Finalize called - too late!");7 // cleanup...8 } finally {9 super.finalize();10 }11 }12}1314// MODERN approach: AutoCloseable + try-with-resources15class ModernResource implements AutoCloseable {16 private boolean open = true;1718 public void use() {19 if (!open) throw new IllegalStateException("Already closed");20 System.out.println("Using resource");21 }2223 @Override24 public void close() {25 open = false;26 System.out.println("Resource closed deterministically");27 }28}2930// Clean, reliable cleanup:31try (ModernResource resource = new ModernResource()) {32 resource.use();33}34// close() called immediately and predictably
Summary: final = constant/immutable. finally = always runs for cleanup. finalize() = deprecated, avoid entirely — use AutoCloseable instead.