Why Java’s Anonymous Inner Classes Restrict Variable Changes (and Kotlin’s Trick)
The article explains why Java’s anonymous inner classes still forbid modifying captured primitive variables after Java 8, how the compiler enforces this by copying values, and why Kotlin can modify them by using reference‑style wrappers.
During development, developers often assume language features are similar across languages, but notable differences emerge when using multiple languages.
Phenomenon Description
Before Java 8, using an external variable inside an anonymous inner class required the variable to be final , otherwise the compiler reported “Cannot refer to a non-final variable …”. After Java 8 the warning disappears, yet attempts to modify the variable still produce an error: “Variable 'num' is accessed from within inner class, need to be final or effectively final”. Kotlin, however, allows direct modification of primitive variables inside anonymous inner classes.
Even after Java 8, when you try to change the variable, the compiler still reports an error, confirming the restriction remains.
The error message becomes “Variable 'num' is accessed from within inner class, need to be final or effectively final”, indicating the variable cannot be altered. In contrast, Kotlin imposes no such limitation.
Kotlin’s compiler wraps primitive values, turning value passing into reference passing, so internal modifications do not affect the outer variable.
Cause Analysis
Inspecting the compiled output of javac reveals several .class files. The file named TestInnerClass$1.class corresponds to the anonymous inner class. Decompiling it shows that the compiler treats the anonymous class like a regular class, generating a constructor that receives both a reference to the outer class and copies of the captured primitive variables, while passing references for object variables. Consequently, the primitive variables cannot be modified inside the inner class because doing so would cause inconsistency with the outer scope.
The decompiled view confirms this handling.
Scenario Comparison
Why can Kotlin modify primitive values inside an anonymous inner class? Decompiling Kotlin’s compiled code shows that Kotlin wraps primitive values, converting value passing into reference passing, allowing internal modifications without affecting the outer variable.
When a variable is not passed at all, Kotlin’s compiler does not add unnecessary wrappers.
Thus, Java’s restriction stems from how the compiler copies primitive values into the anonymous class, while Kotlin’s approach uses reference semantics to avoid the limitation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
