9

I was just exploring java reflection API and i encountered following code snippet

public class Main {
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException{
            Field value=Integer.class.getDeclaredField("value");
            value.setAccessible(true);
            value.set(42, 43);

            System.out.printf("six times seven %d%n",6*7);
            System.out.printf("six times seven %d%n",42);
            System.out.println(42);
        }
    }

Output :

six times seven 43
six times seven 43
42

I read the documentation of the set method which states that it sets value of the field for the given object. But i am not able to understand the output of the code because it should print 42 in all the cases.

Can anyone please give insight into what is happening in the code ?

ATR
  • 2,160
  • 4
  • 22
  • 43

1 Answers1

4
        System.out.println(42);

is calling println(int) not println(Object). The boxing never happens. That makes it faster, and also worked prior to 1.5.

In the other cases, you are boxing through Integer.valueOf(int). This method is defined as always returning exactly the same Integer objects for values between -128 and 127 inclusive (may or may not have the same behaviour for other values). So wherever 42 is boxed in your program you will get the same object, and when you set the value of value in this object it changes no matter which reference it is read through.

If you were to put in the boxing explicitly into the code, it would look like this:

        value.set(Integer.valueOf(42), 43);

        System.out.printf("six times seven %d%n",Integer.valueOf(6*7));
        System.out.printf("six times seven %d%n",Integer.valueOf(42));
        System.out.println(42);

As we know Integer.valueOf( returns exactly the same object for 42, the code is effectively:

        Integer obj42 = Integer.valueOf(42);

        value.set(Integer.valueOf(obj42, 43);

        System.out.printf("six times seven %d%n", obj42);
        System.out.printf("six times seven %d%n", obj42);
        System.out.println(42);
Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • It is little hard to grasp. Can you please give me some reference where can i find more details ? – ATR May 09 '13 at 17:11
  • @ankur.trapasiya Of boxing? The details are in the API docs for `Integer.valueOf` and in the JLS. – Tom Hawtin - tackline May 09 '13 at 17:13
  • @ankur.trapasiya [[Here](http://stackoverflow.com/questions/3130311/weird-java-boxing)] you have interesting question about boxing and caching Integers. Also since `printf(String format, Object ... args)` requires Objects as arguments used in `format` Java will autobox `int` to `Integer`, but since you changed value of cached `Integer` representing 42 to 43, this value will be printed. `println(int)` wont have this problem because it doesn't require boxing. You can also try `System.out.printf("six times seven %d%n",new Integer(6*7));` to create new Integer with value 42 that will not be cached – Pshemo May 09 '13 at 17:16
  • Thanks, understood the problem here. Setting value 43 to the 42 caches the value and as you said it will happen for values between -128 to 127. So any autoboxing will refer to the same object. – ATR May 09 '13 at 17:16