Fundamentals 10 min read

Why Swapping Two Integers Fails in Java? Exploring Pass‑by‑Value, Handles, and Integer Caching

This article dissects a Java interview question about swapping two Integer variables, explaining Java's pass‑by‑value semantics, the difference between handle‑based and direct pointer object access, Integer immutability, autoboxing, the IntegerCache mechanism, and how reflection can (or cannot) modify private final fields.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why Swapping Two Integers Fails in Java? Exploring Pass‑by‑Value, Handles, and Integer Caching

When faced with an interview question that asks to swap two Integer variables, many developers try a straightforward solution that ends up producing incorrect results.

The root cause lies in Java's memory model and how objects are accessed. In the JVM, object references stored in the stack point to either a handle in a handle pool or directly to the object's address in the heap.

Using a handle means the reference stores a stable handle address; the actual object data can move during garbage collection without changing the reference. Direct pointers store the object's address directly, offering faster access but requiring updates when the object moves.

Java passes arguments by value, meaning the method receives a copy of the reference. For primitive types this is a copy of the value; for objects it is a copy of the reference. Therefore, reassigning the parameters inside the method does not affect the original variables.

Although Integer appears to be an object, it is immutable: its internal value field is declared final, and there is no setter to change it. This immutability is similar to String.

One might attempt to bypass immutability using reflection:

However, trying to set a private final field results in an IllegalAccessException unless Field.setAccessible(true) is used. Even then, modifying the cached Integer values only affects the IntegerCache, not the original boxed values used elsewhere.

The JVM maintains an IntegerCache for values between -128 and 127. Calls to Integer.valueOf(int) return cached instances for this range, which explains why certain swaps appear to work for small numbers but not for larger ones.

Bytecode inspection (e.g., javap -c Test.class) shows the compiler automatically inserts boxing and unboxing instructions, confirming the underlying autoboxing behavior.

In summary, the swap fails because Java passes object references by value, Integer objects are immutable, and the IntegerCache mechanism returns shared instances for small values, making direct modification via reflection ineffective for the intended purpose.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ReflectionJDKAutoboxinginteger cachingpass-by-valuememory-model
Java Backend Technology
Written by

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!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.