References to Integer objects in JAVA
There is no pointer in JAVA, but there are also concepts of reference. What we want to talk about here is whether Integer is the same object.
1. Let’s look at a piece of code first:
public static void main(String[] args){ Integer a1 = 100; Integer b1 = a1;//The other one can also be b1=100 Field field = null; try { field = a1.getClass().getDeclaredField("value"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } field.setAccessible(true); try { field.set(a1, 5000); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("b1="+b1); Integer c1 = 100; System.out.println("c1="+c1); } result:
b1=5000
c1=5000
From the above, first of all, I want to explain a few things here.
1) For Integer, the integer between -128-127 has been initialized and placed in IntegerCache. If it is packed, the object will be taken from it.
2) Is b1=a1 a numerical assignment or the same object? This can be seen from the results that b1 and a1 point to the same object, not the same numerical value
3) c1=100 means that for the values between -128-127, all objects obtained from IntegerCache. After the Integer object corresponding to 100 is changed, the subsequent packing of 100 will be changed. Because when obtaining objects in cache, the array index is used, not numerical comparisons are used.
However, modifying this cache will be more dangerous, so don't mind. Who knows which jar package or platform to pack a 100 yuan, but the result is not 100 yuan, and it will crash at that time.
2. Through the above description, what is the answer if it is changed to this
public static void main(String[] args){ Integer a1 = 200; Integer b1 = a1; Field field = null; try { field = a1.getClass().getDeclaredField("value"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } field.setAccessible(true); try { field.set(a1, 5000); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("b1="+b1); Integer c1 = 200; System.out.println("c1="+c1); } 3. Then change it
public static void main(String[] args){ Integer a1 = new Integer(100); Integer b1 = a1; Field field = null; try { field = a1.getClass().getDeclaredField("value"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } field.setAccessible(true); try { field.set(a1, 5000); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("b1="+b1); Integer c1 = 100; System.out.println("c1="+c1); } What is the answer? For new operations, objects are not boxed, but are generated in the heap.
It is not difficult to understand if you understand boxing, caching, and citation. You can try it yourself.
Let's get some basic knowledge first
Correspondence of basic types and wrapper classes byte Byte short Short int Integer long Long float Float double Double char Character boolean Boolean
The correspondence between the basic data types in the above eight is only int->Integer char->Character. The two changes are significant, and the rest are just converting the first letter to lowercase.
Let’s learn about the new features of JDK5: automatic packing and unboxing
Automatic boxing: Convert basic types to packaging class types
Automatic unboxing: Convert the wrapper class type to the basic type
public class Demo_Integer { public static void main(String[] args) { //Before JDK1.5 int a = 100; Integer a1 = new Integer(a); //Wrap the basic data type into an object, box int b = a1.intValue(); //Convert the object to the basic data type and unbox //After JDK1.5 int x = 100; Integer x1 = x; //Automatically box, convert the basic data type into an object int y = x1 + x; //Automatically unbox, convert the object to the basic data type} }Things to note
public class Demo_Integer { public static void main(String[] args) { Integer a = null; int b = a + 100; //The bottom layer of automatic unboxing will call a.intValue(), a is null, and a will naturally throw NullPointerException System.out.println(b); } }Interview questions
public class Demo_Integer { public static void main(String[] args) { Integer i1 = new Integer(97); Integer i2 = new Integer(97); System.out.println(i1 == i2); System.out.println(i1.equals(i2)); System.out.println("-------------"); Integer i3 = new Integer(197); Integer i4 = new Integer(197); System.out.println(i3 == i4); System.out.println(i3.equals(i4)); System.out.println("----------------"); } }Output: false true ----------------------------------
reason:
new is to open up space in heap memory, and the natural comparison address value (==) is false.
Since Integer rewrites the equals method, the equals output is true.
You may feel that it is too simple and has no technical content, because the above is not the point, look at the code below
public class Demo_Integer { public static void main(String[] args) { Integer i1 = 127; Integer i2 = 127; System.out.println(i1 == i2); System.out.println(i1.equals(i2)); System.out.println("--------------"); Integer i3 = 128; Integer i4 = 128; System.out.println(i3 == i4); System.out.println(i3.equals(i4)); System.out.println("---------------"); } }Output: true true ------------------------------------------
reason:
Why do two objects when int is greater than 127? Does the number 127 feel very familiar?
-128 to 127 are the value range of byte. If it is within this value range, automatic boxing will not create a new object, and get it from the constant pool
If the value range of byte is exceeded, a new object will be created.
Automatically pack the underlying layer and call the valueOf() method, simple source code analysis (JDK1.8):
public final class Integer extends Number implements Comparable<Integer> { public static Integer valueOf(int i) { //When i >= -128 and i <= 127, the object in the buffer will be directly retrieved if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);//If the byte value range exceeds the range, it will be created in heap memory} //The inner class acts as a buffer 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 internalized (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} } } 8 basic types of wrapping classes and object pools
Most of the basic types of wrapper classes in Java implement constant pooling technology. These classes are Byte, Short, Integer, Long, Character, Boolean, and the other two types of wrapper classes with floating point number are not implemented. In addition, the five integer wrapper classes of Byte, Short, Integer, Long, Character can only use the object pool when the corresponding value is less than or equal to 127, that is, the object is not responsible for creating and managing objects of these classes greater than 127.
Extended knowledge
In the jvm specification, each type has its own constant pool. A constant pool is an ordered collection of constants used by a certain type, including direct constants (primitive types, Strings) and symbolic references to other types, fields, and methods. The reason why it is symbolic reference rather than directly specifying other types at compile time is because Java is dynamically bound, and only at runtime can the specific dependency instances of type are determined according to certain rules. This is the basis for Java to implement polymorphism.
In the JVM, the entire life cycle of a class starts from being loaded into the virtual machine memory and until it is unloaded out of memory. Its entire life cycle includes: loading, verification, preparation, parsing, initialization, use and unloading. The parsing stage is the process of the virtual machine replacing symbol references in the constant pool with direct references.
Summarize
The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support to Wulin.com.