“This is the 22nd day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
The paper
It may seem surprising that this problem can be solved with a little Java syntax.
1. Solution:
The Java expert group found that most of the data initialized by Integer objects is between -128 127, so Integer presets the cache for small data (-128 127) to improve the performance of instantiating an Integer in most cases. The solution is that when the JVM initializes, the number between -128 127 is cached in local memory. If the number between -128 127 is initialized, it is fetched directly from memory without creating a new object. Instead, the data is cached in Integer’s internal class IntegerCache. 1==2==3; 1==2==3; 1== 1; 2==3;
2, Integer internal class IntegerCache source
Sample source code:
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
3. Concrete implementation
Code examples:
package com.lizba.p3; import java.lang.reflect.Field; / * * * * < p > a = = 1 & & & & a = = a = = 2 3 sample code * < / p > * * @ Author: Liziba * @ the Date: 2021/6/3 17:19 */ public class IntegerTest { public static void main(String[] args){ try { Class<? >[] declaredClasses = Integer.class.getDeclaredClasses(); Class<? > integerCache = declaredClasses[0]; Field f = integerCache.getDeclaredField("cache"); f.setAccessible(true); Integer[] cache = (Integer[]) f.get(integerCache); System.out.println(cache[129]); System.out.println(cache[130]); System.out.println(cache[131]); cache[130] = cache[129]; cache[131] = cache[129]; Integer a = 1; // true if (a == (Integer) 1 && a == (Integer) 2 && a == (Integer) 3) { System.out.println(true); } // true if (a == Integer.valueOf(1) && a == Integer.valueOf(2) && a == Integer.valueOf(3)) { System.out.println(true); } // No output if (a == new Integer(1) && a == new Integer(2) && a == new Integer(3)) {system.out.println (true); } System.out.println(cache[129]); System.out.println(cache[130]); System.out.println(cache[131]); } catch (Exception e) { e.printStackTrace(); }}}Copy the code
Viewing the output
4. Pay attention
Why are the first two true and the last false?
// true if (a == (Integer) 1 && a == (Integer) 2 && a == (Integer) 3) { System.out.println(true); } // true if (a == Integer.valueOf(1) && a == Integer.valueOf(2) && a == Integer.valueOf(3)) { System.out.println(true); } // No output if (a == new Integer(1) && a == new Integer(2) && a == new Integer(3)) {system.out.println (true); }Copy the code
The answer can be found in the source code:
When we construct an Integer with the new keyword, it is an object that is being re-instantiated in the JVM, so the object addresses are not equal.
/**
* The value of the {@code Integer}.
*
* @serial
*/
private final int value;
/**
* 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;
}
Copy the code
When integer.valueof (int) is used, the values between -128 and 127 are retrieved from IntegerCache, and the same object with the same address is returned.
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
5, summary
These knowledge points are used to test a developer’s proficiency in JDK features and the accumulation of time, sometimes if asked is also useful, or give us in the actual development of data preheating to improve the performance of the service, brought a certain thinking value.