Integer cache Java – Curiosidades

Hace ya tiempo, que cuando preguntas a alguien, que devuelve la operación siguiente.

        Integer a = 5;
        Integer b = 5;
        System.out.println((a==b) == (a.equals(b)));

Como podéis ver es una respuesta booleana, pero en realidad tiene tres respuesta y tiene: una menos mala, una mala y una buena.

En primer lugar tenemos la respuesta menos mala, que es cuando la persona te dice: Pues la teoría dice que equals comparas valor y igual comparas referencias. Exactamente es una respuesta totalmente licita, por lo que esta persona te responde false.

En segundo lugar tenemos a la persona que no sabe de teoría, simplemente, programa a fuerza de IDE y si ve que no compila o tiene un error, cambia de estrategia i listos, pero mirar él porque tampoco va mucho con él. Seguramente se lo expliques y mañana no se acuerde, benditos IDEs.

En tercer lugar, tenemos a alguien que ha tenido un poco curiosidad y ha entrado en el fabuloso mundo de la JVM y te responden true, porque Integer desde la 1.5, tiene implementado un sistema de cache, por performance, que modifica el comportamiento desde -128 a 127. Aunque en este grupo también hay los que algo intuyen pero se pegan, lo que llamaríamos un naide. “como por ejemplo, eso es unboxing.”

Integer class (IntegerCache)

/**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    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() {}
    }

Como podéis ver esta particularidad es debido al “autoboxing” esta particularidad sucede cuando asignamos el valor a una variable Integer var = 5, no necesitamos ningún método par convertir el int a integer porque JVM hace un “autoboxing“.

Vamos a rizar el rizo y sigamos mirando Integer..

Integer (valueOf)


    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

Si intentamos hacer, el mismo experimento instanciando uno con 5 y otro con valueOf(5), el resultado sería el mismo… Mierda!

Pero, OMG mira ese constructor

/**
 * Constructs a newly allocated {@code Integer} object that
 * represents the specified {@code int} value.
 *
 * @param   value   the value to be represented by the
 *                  {@code Integer} object.
 */
public Integer(int value) {
    this.value = value;
}

Hagamos una prueba

Pues eso señores, esto no es más que una curiosidad, que no sirve para nada, porque ya sabéis que debéis usar equals para los objetos!

Deja una respuesta

A %d blogueros les gusta esto: