细数java中Long与Integer比较容易犯的错误总结
今天使用findbugs扫描项目后发现很多高危漏洞,其中非常常见的一个是比较两个long或integer时直接使用的==来比较。 其实这样是错误的。
因为long与ineger都是包装类型,是对象。 而不是普通类型long与int , 所以它们在比较时必须都应该用equals,或者先使用longvalue()或intvalue()方法来得到他们的基本类型的值然后使用==比较也是可以的。
但是有一种特殊情况, 其实long与integer都将 -128~127 这些对象缓存了。 可以看看long类型源码里面有一个longcache类,代码如下:
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); } }
先看看这个例子:
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)); } }
打印的结果是:
a == b ? true c == d ? false
原因
首先来看看 long a = 5l ; 它是如何将一个基本类型long包装成一个对象long的 。
可以写一个测试类,然后反编译一下,看看java它是如何解析long a = 5l这样一条命令的 。
测试类如下:
public class test06 { long l = 3l; }
然后使用javap -verbose test06 就能看到反编译的结果了, 下面是输出的部分:
{ 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; }
从code中的8可以看出调用了long的一个类方法long.valueof(long) , 所以可以得到的结论是long a = 5l实际上等于 long a = long.valueof(5) ;
然后再看看long.valueof()方法是如何定义的:
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); }
一目了然,会先判断基本类型的值如果在-128~127之间,就会直接从longcache里面取出缓存的对象返回,否则就new一个新的long对象返回 。
现在就不难理解test05程序执行得到的结果了,因为a与b等于5,在-127~128之内,所以都是直接从longcache里面返回的一个long对象,所以他们在使用==比较的时候,就是相等的(对于对象类型来说,==比较的是两个对象的引用指向堆中的地址) ,而c与d等于129,不在-127~128之间,所以他们他们是分别new出来的两个新的long对象,使用==来比较自然是不相等的了。
long重写了equals方法:
public boolean equals(object obj) { if (obj instanceof long) { return value == ((long)obj).longvalue(); } return false; }
它是先通过.longvalue()方法获取long对象的基本类型long的值之后再做比较的。
所以对于integer与long的比较,最好是使用equals来比较才能确保得到我们想要的结果。
integer与long一样,这里就不举例了。
以上这篇细数java中long与integer比较容易犯的错误总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。