Saturday, June 13, 2026

Java 26: min() and max() in Comparator

Java 26 adds two small but very useful default methods to the Comparator interface: min and max.

Consider the following comparator:

Comparator<Person> ageComparator =
        Comparator.comparingInt(Person::age);

Before Java 26, finding the older of two people was awkward:

ageComparator.compare(alice, bob) > 0 ? alice : bob

// alternatively, use Stream.max:
Stream.of(alice, bob).max(ageComparator).get()

With Java 26, it becomes much cleaner:

Person older = ageComparator.max(alice, bob);
Person younger = ageComparator.min(alice, bob);

Saturday, June 06, 2026

Java 26: Mutating Final Fields Using Reflection

Java 26 introduces a new warning when code uses reflection to mutate final fields. This change comes from JEP 500: Prepare to Make Final Mean Final, and is part of Java’s ongoing move toward stronger integrity and better JVM optimisations. The JVM relies on the assumption that final fields never change in order to perform optimisations such as constant folding and safe object initialisation in concurrent code. However, deep reflection APIs like Field.setAccessible(true) and Field.set(...) have historically allowed any code to mutate final fields at runtime, breaking those guarantees.

Consider the following code that reflectively mutates a final field:

public class Foo {

  final int x;

  Foo() {
    x = 100;
  }

  public static void main(String... args) 
                          throws Exception {

    Foo obj = new Foo();

    System.out.println(obj.x);
    
    java.lang.reflect.Field f =
            Foo.class.getDeclaredField("x");
    f.setAccessible(true);
    f.set(obj, 200); // mutate the final field

    System.out.println(obj.x);
  }
}

In older JDK versions, this would silently mutate the supposedly immutable final field.

In JDK 26, it still works, but produces warnings:

100
WARNING: Final field x in class Foo has been mutated reflectively by class Foo in unnamed module @764c12b6
WARNING: Use --enable-final-field-mutation=ALL-UNNAMED to avoid a warning
WARNING: Mutating final fields will be blocked in a future release unless final field mutation is enabled
200

In a future JDK release, these operations are expected to fail unless explicitly enabled using --enable-final-field-mutation=ALL-UNNAMED or for specific modules --enable-final-field-mutation=M1,M2.

So, stop mutating final fields! final means final.