Errors that Long and Integer are prone to in JAVA
Today, we found many high-risk vulnerabilities after using the findbugs scan project. One of the most common ones is to compare two Long or Integer values directly using =. In fact, this is wrong.
Because Long and Ineger are both packaging types and are objects. Instead of common long and int types, equals must be used for comparison, or longValue () or intValue () must be used first () method to obtain the value of their basic type and then use = to compare it.
However, there is a special case where both Long and Integer convert to-128 ~ 127 these objects are cached. You can see that there is a LongCache class in the Long source code. The Code is as follows:
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);} }
Let's take a look at this example:
public class Test05 { public static void main(String[] args) { Long a = 5L; Long b = 5L; System.out.println("a == b ? " + (a == b)); Long c = 129L; Long d = 129L; System.out.println("c == d ? " + (c == d)); }}
The printed result is:
a == b ? truec == d ? false
Cause
First let's take a look at how Long a = 5L; it wraps a basic type long into an object Long.
You can write a test class and decompile it to see how java parses a command such as Long a = 5L.
The test class is as follows:
public class Test06 { Long l = 3L;}
Then you can use javap-verbose Test06 to view the decompilation result. The output section is as follows:
{java.lang.Long l;public com.spring.test.Test06(); Code: Stack=3, Locals=1, Args_size=1 0: aload_0 1: invokespecial #10; //Method java/lang/Object."
":()V 4: aload_0 5: ldc2_w #12; //long 3l 8: invokestatic #14; //Method java/lang/Long.valueOf:(J)Ljava/lang/Long; 11: putfield #20; //Field l:Ljava/lang/Long; 14: return LineNumberTable: line 3: 0 line 5: 4 line 3: 14 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this Lcom/spring/test/Test06;}
We can see from Code 8 that a Long class method is called. valueOf (Long), so we can conclude that Long a = 5L is actually equal to Long a = Long. valueOf (5 );
Then let's see how the Long. valueOf () method is defined:
public static Long valueOf(long l) {final int offset = 128;if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset];} return new Long(l); }
At a glance, the system will first determine the value of the basic type if it is in-128 ~ Between 127, the cached object is directly retrieved from LongCache, otherwise a new Long object is returned.
Now it is not difficult to understand the result of the execution of the Test05 program, because a and B are equal to 5, in-127 ~ Within 128, it is a Long object directly returned from LongCache, so they are equal when using = for comparison (for object types, = compare the reference of two objects pointing to the address in the heap), while c and d are equal to 129, not-127 ~ Between 128, so they are two new Long objects respectively. Using = is naturally not equal.
Long overrides the equals method:
public boolean equals(Object obj) {if (obj instanceof Long) { return value == ((Long)obj).longValue();}return false; }
It first obtains the value of the Long object of the basic type through the. longValue () method and then compares it.
Therefore, it is best to use equals to compare Integer and Long to ensure that the expected results are obtained.
Integer is the same as Long.