Today I used findbugs to scan the project and found many high-risk vulnerabilities. One of the very common ones is the direct use of == when comparing two Long or Integer. In fact, this is wrong.
Because Long and Ineger are both packaging types and objects. Instead of ordinary types long and int, they must use equals when comparing, or you can first use the longValue() or intValue() method to get their basic type values and then use == to compare.
But there is a special case. In fact, both Long and Integer cache objects -128~127. You can look at the Long type source code and there is a LongCache class. 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 first:
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 ? true c == d ? false
Reason
First let’s take a look at Long a = 5L; how it wraps a basic type long into an object Long.
You can write a test class and then decompile it to see how java parses a command like Long a = 5L.
The test class is as follows:
public class Test06 { Long l = 3L; }
Then use javap -verbose Test06 to see the decompilation results. The following is the output part:
{ 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."<init>":()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; }
It can be seen from 8 in Code that a class method Long.valueOf(Long) of Long is called, so the conclusion that can be drawn is that Long a = 5L is actually equal to Long a = Long.valueOf(5) ;
Then look at 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); }
It is clear at a glance that if the value of the basic type is between -128 and 127, the cached object will be retrieved directly from the LongCache and returned. Otherwise, a new Long object will be returned.
Now it is not difficult to understand the results of the Test05 program execution, because a and b are equal to 5, within -127~128, so they are both a Long object returned directly from LongCache, so they are When compared using ==, they are equal (for object types, == compares the addresses in the heap that the references of the two objects point to), and c and d are equal to 129, not between -127~128, so They are two new Long objects created separately. Naturally, they are not equal when compared using ==.
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 basic type long of the Long object through the .longValue() method and then compares it.
So for the comparison between Integer and Long, it is best to use equals to ensure that we get the results we want.
Integer is the same as Long, so I won’t give an example here.
The above summary of the common mistakes of Long and Integer in Java is all the content shared by the editor. I hope it can give you a reference, and I also hope that everyone will support the PHP Chinese website.
For more details on the common mistakes of Long and Integer in Java, please pay attention to the PHP Chinese website for related articles!