The main ideas of this paper are as follows:
No matter from work or interview, this article should be read, I think it is very useful.
case
Integer is a wrapper class for the basic int. Usually, whether you have been in the pit for many years or you are on the way to the pit, you should know that the frequency of use is quite high.
The order payment state enumeration class PayStatusEnum is created to simulate order payment
public class IntegerDemo {
public static void main(String[] args) {
Integer a = new Integer(8);
Integer b = Integer.valueOf(8);
Integer c = 8; System.out.println(a.equals(b)); System.out.println(a.equals(c)); System.out.println(b.equals(c)); System.out.println(a == b); System.out.println(a == c); System.out.println(b == c); }}Copy the code
What is the output?
After changing 8 to 128 in the above code, what is output?
public class IntegerDemo {
public static void main(String[] args) {
Integer a = new Integer(128);
Integer b = Integer.valueOf(128);
Integer c = 128; System.out.println(a.equals(b)); System.out.println(a.equals(c)); System.out.println(b.equals(c)); System.out.println(a == b); System.out.println(a == c); System.out.println(b == c); }}Copy the code
The answer comes slowly.
Analytical case
Integer Indicates the overall view
A constructor
private final int value;
public Integer(int value) {
this.value = value;
}
Copy the code
It’s too simple. There’s nothing to say.
The valueOf () method
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
/ / @ HotSpotIntrinsicCandidate the annotations are JDK9 was introduced
/ / HotSpot virtual machine to mark the @ HotSpotIntrinsicCandidate annotation method calls,
// Instead, use efficient implementations directly based on specific CPU instructions. These methods are referred to as intrinsics.
public static Integer valueOf(int i) {
// Cache is used if I is between low and high
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
Copy the code
The valueOf() method uses IntegerCache, so let’s talk about it.
IntegerCache
IntegerCache source code and some comments:
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as Required by JLS. * The JLS protocol requires caching between -128 and 127 (including boundary values) * * The cache is initialized on first usage. * When The program first uses The Integer * The size of the cache may be controlled by the {@code-xx :AutoBoxCacheMax=<size>} Option. * JVM boot parameter -xx :AutoBoxCacheMax=size Changes the maximum value * 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. * can be gained through the system properties: - Djava. Lang. Integer. IntegerCache. High = < size > * /
private static class IntegerCache {
static final int low = -128;
static final int high;
// Use arrays to cache constant pools
static final Integer cache[];
static {
// high value may be configured by property
// The maximum value is configurable
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
-xx :AutoBoxCacheMax=
if(integerCacheHighPropValue ! =null) {
try {
int i = parseInt(integerCacheHighPropValue);
// Compare 127 with 127
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
// Get the minimum value
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
// If the value is incorrect, ignore the value and use the default range -128 to 127
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
// Caching is implemented through a for loop, which creates a range of integer objects and stores them in the cache array
// The first time a program uses Integer it takes some extra time to initialize the cache
for(int k = 0; k < cache.length; k++){
cache[k] = new Integer(j++);
}
// In any case, the maximum value of the cache must be greater than or equal to 127
assert IntegerCache.high >= 127;
}
// Private constructor, because all attributes are class constants
private IntegerCache(a) {}}Copy the code
The entire static block logic is:
So, how to set up the Java. Lang. Integer. IntegerCache. High value?
The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=} option.
As stated in the comments, you can use the -xx :AutoBoxCacheMax= setting.
Write a demo to debug it
public class IntegerDemo {
public static void main(String[] args) {
Integer a = 8;
Integer b =Integer.valueOf(8); System.out.println(a.equals(b)); System.out.println(a == b); }}Copy the code
Settings – XX: AutoBoxCacheMax = 100
To start the debug
Look at the value of high
It’s 127. That’s right, because up there
Settings – XX: AutoBoxCacheMax = 130
Enabling the Debug mode
Note: low=-128 does not change. The cache initialization process does not change low, and low is constant.
-xx: What is the maximum value of AutoBoxCacheMax?
Since the maximum value of Integer is 2147483647, let’s try using that value here,
Start debug, go straight to OOM
Why OOM?
If -xx :AutoBoxCacheMax is not set, the array looks like this.
The equals () method
The equals method was used in the example above, so let’s talk about it here
private final int value;
public boolean equals(Object obj) {
if (obj instanceof Integer) {
// Compare two values of type int
return value == ((Integer)obj).intValue();
}
//obj is not an Integer and returns false
return false;
}
Copy the code
Go back to the example above
When we use the equals method to compare whether two objects are equal, we are actually comparing their values.
So whether it’s 128 or 8, equals must always be true.
When a reference type uses == to compare the addresses of two referenced objects, it compares whether they are the same.
public class IntegerDemo {
public static void main(String[] args) {
Integer a = new Integer(8);
Integer b = Integer.valueOf(8);
Integer c = 8; System.out.println(a.equals(b)); System.out.println(a.equals(c)); System.out.println(b.equals(c)); System.out.println(a == b); System.out.println(a == c); System.out.println(b == c); }}Copy the code
Let’s look at the bytecode in the class file;
Local variable scale
The process of assigning a value to each local variable
Here we can draw a conclusion:
Integer c =8; So Integer c = integer.valueof (8);
Above Integer b = integer.valueof (8); , which means that variables B and c are both fetched using integer.valueof ().
The valueOf method
– XX: AutoBoxCacheMax is not set
The low and high values for IntegerCache have been explained above. Low is always -128, so when we don’t set it
-xx :AutoBoxCacheMax value, high=127.
When an Integer. The valueOf (8); Is entered into the if in the code above. It is then fetched from the array cache in IntegerCache.
But the cache array in an IntegerCache is a constant array.
The implication is that once the array cache is assigned, it does not change.
Integer b = Integer.valueOf(8); And the Integer c = 8;
B and C both refer to the same reference address.
So b==c is true;
But the Integer b = Integer. The valueOf (128);
Instead of going into the if, we’re going to just new an Integer object
So at this time
The Integer b = Innteger. The valueOf (128); And Integer C = 128;
They each new an Integer object,
B ==c is false.
Int I is in the range of -128 to 127.
-xx: Set AutoBoxCacheMax to 130
If we set -xx :AutoBoxCacheMax to 130. So the above
The Integer b = Innteger. The valueOf (128); And Integer C = 128;
It also goes into the if condition.
Finally b==c is true.
How to avoid the pit
Integer is a class that encapsulates the basic int type. Note the following:
1. If Integer is used, note that the default value of Integer is null, which may cause NullPointerException.
2. If you’re using an int, note that the initial value of an int is 0.
3. In addition, in terms of memory usage, int is a basic data type, occupying only 4 bytes, while Integer is an object. When representing a value, Integer occupies more memory space than int.
Integer c = 8, not new Integer(8). Because direct assignment is integer. valueOf using the cache, there is no need to create a new object every time, effectively increasing memory usage.
5, if the system uses a number larger than 127 repeatedly, it is recommended that the JVM boot with -xx :AutoBoxCacheMax=size to improve memory efficiency (but not too large, as we demonstrated above where OOM is possible).
The interview questions
The interview questions 1
Integer num1 = new Integer(10);
Integer num2 = new Integer(10);
System.out.println(num1.equals(num2));
System.out.println(num1 == num2);
Copy the code
The interview questions 2
Integer num3 = 100;
Integer num4 = 100;
System.out.println(num3.equals(num4));
System.out.println(num3 == num4);
Copy the code
The interview question 3
Integer num5 = 1000;
Integer num6 = 1000;
System.out.println(num5.equals(num6));
System.out.println(num5 == num6);
Copy the code
Finish reading above, come back to see this kind of interview question, still difficult?
If you encounter interview question 3 during the interview, it is appropriate to ask the interviewer if they have adjusted the cache scope. Some interviewers may be confused.
Hit the interviewer naked.
conclusion
1. Reference type == compares the corresponding reference address.
2. The default cache used in Integer is -128 to 127. However, it can be set at JVM startup time.
3.Integer b=Integer.valueOf(8); And the Integer b = 8; It’s the same effect.
4. Integer.valueof () compares whether an Integer object is within the range of the cache. If an Integer object is within the range of the cache, it is directly fetched from the cache.
5. The IntegerCache is not used every time an Integer object is created using new.
6. The use of caching in Integer can also be interpreted as the share mode.