The reason why I wrote this blog is that I met a problem when I was learning JavaSE. It extends from solving problems to summarizing such problems. I would like to talk about how to solve this problem.
First, let's talk about "==". In java "==" means the comparison value. For basic data types, "==" is the value of the ratio, which is no doubt; the main point is that for reference data types, "==" is not the value of the object, but the address of the object!!!
It seems that there is nothing to say about this, but for the packaging classes in the reference type, because they have the characteristics of automatic packing and automatic unpacking, it is confusing to use "==" to compare the equality of the two packaging classes at the beginning of school. Next, make a detailed comparison and description of all packaging classes and String classes! First, we discuss non-new creation objects in wrapper classes!
Byte's "==" comparison
Test source code
public class ByteBoxing { public static void main(String[] args) { //byte range - 128 ~ 127 Byte b = 1; Byte b1 = 1; System.out.println(b == b1);//The test result is true. Byte b2 = 120; Byte b3 = 120; System.out.println(b2 == b3);//The test result is true. } }
The test found that: b=b1, that is to say, B and B1 point to the same object! Why? The following is part of the source code for the Byte class:
private static class ByteCache { private ByteCache(){} static final Byte cache[] = new Byte[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Byte((byte)(i - 128)); } }
As can be seen from the screenshot, the Byte type automatically generates a constant object of 256 Bytes when the class is loaded, that is to say, 256 objects are unchanged all the time, and the values are from - 128 to + 127! This means that the Byte type is cached! The cache is 256 objects with values ranging from - 128 to 127! When creating b, we first look for the cached object in the heap to see if there is an object with the same value as B. If there is one, we will add the address of the cached object to B. So when using the above code to create objects, they will first find the cache object, if not equal, then open up an object in the heap! So as long as the value of B is between - 128 and 127, then there is no need to open up the object, directly give the address of the cached object to the variable to be referenced. This leads to the operation of b1, to find the cached object, found that there is already a cached object, the address of the cached object is assigned to b1. This is the result of B = b1, true!
2. Short's "==" comparison
Test source code:
public class ShortBoxing { public static void main(String[] args) { Short s = 1; Short s1 = 1; System.out.println(s == s1);//The execution result is true @ 1 Short s2 = 150; Short s3 = 150; System.out.println(s2 == s3); //The execution result is false @ 2 } }
The result of @2 is flase. It's a bit confusing. Don't panic. Let's see how Short's source code is designed.
private static class ShortCache { private ShortCache(){} static final Short cache[] = new Short[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Short((short)(i - 128)); } }
From the figure, we can see that the Short source code also designed 256 cached objects, the value is - 128 to 127, so as long as the value of the object to be created by Short is in this interval, it is no longer necessary to open up new space, it is OK to directly give the address of the cached object to the reference variable! So when using "==" comparison, it will be equal; but the value is beyond the range of cached value, then only a new object comes out. At this time (as long as it is a new object), the use of "==" is different!
3. Integer type "==" comparison
Test source code:
public class IntegerBoxing { public static void main(String[] args) { Integer i = 1; Integer i1 = 1; System.out.println(i = i1);//The answer is: true } }
From the point of view of Byte and Short's solution, let's first look at the source code design of Integer in java, whether there is a cache, and if so, how big is the cache size and how much is the value! Here's a screenshot
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) { 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); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }
4. Long type "==" comparison
Test source code:
public class LongBoxing { public static void main(String[] args) { Long m = 2l; Long n = 2l; System.out.println(m == n);//The result is: true } }
In the same way, look at Long's source code design, as shown below
private static class LongCache { private LongCache(){} static final Long cache[] = new Long[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Long(i - 128); } }
Likewise, Long, like Integer and Byte, has 256 cached objects with values ranging from - 128 to 127!
5. Float type, Double type
Test source code:
public class FloatBoxing { public static void main(String[] args) { Float f = 12f; Float f1 = 12 f; System.out.println(f == f1); //!!! The result is false. } } public class DoubleBoxing { public static void main(String[] args) { Double d = 1.0; Double d1 = 1.0; System.out.println(d == d1); //!!! The result is false. } }
As you can see from the figure, even if the values of float and double are in the range - 128 to 127, the result is false. Is the source code design of Flaot and Double in java different from the packing class of integer type? So let's go to the source code and see what's going on.
!!! Looked at the source code of Float and Double, there is no cache design in it!!! This should be distinguished from the previous one.
6.Character type "=="
Test source code:
public class CharacterBoxing { public static void main(String[] args) { Character c = ' '; //Null character, corresponding to asscii code value of 0 Character c1= ' '; System.out.println(c == c1); //The result is true } }
From the test results, Character is cached. Let's look at the design of the source code.
private static class CharacterCache { private CharacterCache(){} static final Character cache[] = new Character[127 + 1]; static { for (int i = 0; i < cache.length; i++) cache[i] = new Character((char)i); } }
As you can see from the source code, Character has 128 caches, ranging from 0 to 128. (Specific symbols need to correspond to the asscii code table)
================
Okay, here we're going to solve the "==" problem caused by the cache design of String and wrapper classes. Cache design is because these are the data objects we often use. Setting reasonable caches can greatly improve our code execution speed (no more space and time consuming) and save memory space (no repetition of new objects).
Next, let's talk about equals, which is a way to judge the relationship between two objects. This method is a method that comes with the Object class. All classes are subclasses of the Object class, so each class has an equals method inherited from Object. However, in many cases, the inherited judgment method is not suitable for the personalized comparison of the current class, so many system classes are rewritten equals method! So when we find that the results obtained by using equals method are not satisfactory, we must go and see if this kind of method is not rewriting equals method. If it is rewriting, what are the rules of rewriting? That's what I want to say!
Let's first look at the rules for comparing equals methods in Object classes:
We see that the equals method without rewriting is the reference address of the comparison object; then let's look at the equals method of the wrapper class:
We see that the equals method in the wrapper class in 8 is rewritten. The rewriting rule is to compare the size of the object's value and not to compare the reference address anymore. Then let's look at the equals method of the String class.
We can see that the equals method of String class is also rewritten, and the rewriting rule compares whether the values of two strings are the same. If the values are the same, it returns true.