How does the "final" keyword in Java work? (I can still modify an object.)

In Java, the final keyword can be used in several contexts to declare that something cannot be changed.

When applied to a variable, it means that the value of the variable cannot be changed once it has been assigned. For example:

final int x = 10;
x = 20; // This will cause a compile-error, because x is final and cannot be reassigned

When applied to a method, it means that the method cannot be overridden in a subclass. For example:

public class MyClass {
  public final void myMethod() {
    // Method implementation
  }
}

public class MySubclass extends MyClass {
  public void myMethod() {
    // This will cause a compile-error, because myMethod is final and cannot be overridden
  }
}

When applied to a class, it means that the class cannot be subclassed. For example:

public final class MyClass {
  // Class implementation
}

public class MySubclass extends MyClass {
  // This will cause a compile-error, because MyClass is final and cannot be subclassed
}

However, it is important to note that the final keyword only affects the variable, method, or class itself, and not the objects or instances that are created from it. For example:

final List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");

names = new ArrayList<>(); // This will cause a compile-error, because names is final and cannot be reassigned

names.add("Eve"); // This is allowed, because we are not modifying the reference itself, only the object it refers to

In this example, the names variable is a reference to an ArrayList object, and the final keyword prevents the reference from being reassigned to refer to a different object. However, the ArrayList object itself can still be modified, because it is not marked as final.