Java is an almost pure object-oriented programming language, but it still introduces basic data types for programming convenience. In order to treat these basic data types as objects, Java introduces a corresponding Wrapper class for each basic data type. The wrapper class for int is Integer, and since Java5 automatic boxing/unboxing has been introduced to make the two interchangeable. Java provides a wrapper type for each primitive type:

  • Primitive types: Boolean, char, byte, short, int, long, float, double
  • Wrapper types :Boolean, Character, Byte, Short, Integer, Long, Float, Double

It’s easy to assume that both outputs are either true or false if you don’t know what you’re doing. The first thing to note is that the variables f1, f2, f3, and F4 are all Integer object references, so the == operation below compares references rather than values. What is the nature of packing? When we assign an int value to an Integer object, valueOf, the static method of the Integer class, is called. If you look at valueOf’s source code, you can see what happens.

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
Copy the code

IntegerCache is the inner class of Integer, and its code looks like this:

private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue ! = null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) Assert IntegerCache. High >= 127; } private IntegerCache() {} }Copy the code

To put it simply, if the Integer literal is between -128 and 127, then no new Integer object will be created. Instead, the Integer object in the constant pool will be referenced directly. And f3==f4 is false.