import java.lang.reflect.Field; /** * JEP 500 (Java 26): "Prepare to Make Final Mean Final". Deep reflection on a final field * (Field.setAccessible(true) followed by Field.setInt) used to work silently. On 26 it works but * warns once; a future release will deny it unless you opt in. * * The same file is run five ways by scripts/recap26.sh; the transcript is docs/output/70-final-field-mutation.txt. * Chapter: docs/11-recap-26.md */ public class FinalFieldMutation { static class Config { private final int port = 8080; int port() { return port; } } public static void main(String[] args) throws Exception { Config c = new Config(); Field f = Config.class.getDeclaredField("port"); f.setAccessible(true); try { f.setInt(c, 9090); } catch (IllegalAccessException e) { System.out.println("setInt refused : " + e.getMessage()); return; } // The field reads 9090 but port() still says 8080: 'final int port = 8080' is a constant variable, so javac // copied the literal 8080 into port() at compile time. Nothing you write to the field can reach that copy. // That silent disagreement is the reason the platform wants this to stop, not a hypothetical. System.out.println("field reads : " + f.getInt(c)); System.out.println("port() returns : " + c.port()); } }