Java-Integer好大一坑,一不小心就掉进去了 - 遛马少年
source link: https://www.cnblogs.com/liumashaonian/p/17107167.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Java-Integer好大一坑,一不小心就掉进去了
遛马少年,一个代码写的很6的程序员,专注于技术干货分享
最近,在处理线上bug的时候,发现了一个奇怪的现象
业务代码大概是这样的
public static boolean doSth(Integer x, Integer y) {
if (x == y) {
return true;
}
//do other...
return false;
}
当x、y都是较小的值时,比如100、100,正常返回true
当是较大值时,比如500、500,反而返回false
难道100==100,500!=500吗?
带着这样的疑问,我写了个demo程序一探究竟
public class IntDemo {
public static boolean doSth(Integer a, Integer b) {
if (a == b) {
return true;
}
return false;
}
public static void main(String[] args) {
int a = 100;
int b = 500;
System.out.println(doSth(a, a));
System.out.println(doSth(b, b));
}
}
输出结果为:
奇怪!底层是怎么处理的呢?我用javap看了一下上面代码的字节码指令
public class com.integer.IntDemo {
public com.integer.IntDemo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static boolean doSth(java.lang.Integer, java.lang.Integer);
Code:
0: aload_0
1: aload_1
2: if_acmpne 7
5: iconst_1
6: ireturn
7: iconst_0
8: ireturn
public static void main(java.lang.String[]);
Code:
0: bipush 100
2: istore_1
3: sipush 500
6: istore_2
7: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
10: iload_1
11: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
14: iload_1
15: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
18: invokestatic #4 // Method doSth:(Ljava/lang/Integer;Ljava/lang/Integer;)Z
21: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
24: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
27: iload_2
28: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
31: iload_2
32: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
35: invokestatic #4 // Method doSth:(Ljava/lang/Integer;Ljava/lang/Integer;)Z
38: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
41: return
}
可以看到,doSth函数传入的实参是int类型,函数定义的形参却是Integer类型
看到第11行字节码指令我就懂了,原来是通过Integer.valueOf 来做的一个int的自动装箱
11: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
所以,问题肯定出在Integer.valueOf里面,接着,我点开valueOf的源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
好家伙,这里用到了一个缓存类:IntegerCache
判断如果在缓存范围内,直接返回这个缓存类持有的引用,否则就new一个Integer对象
再点开这个缓存类,low=-128,high=127
这就解释了为什么100是true,500是false了
JDK为什么要设计这样一个很容易掉进去的坑呢?
其实,在valueOf方法上,官方已经给出了说明:
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
大概意思就是,-128~127 的数据在 int 范围内是使用最频繁的,为了减少频繁创建对象带来的内存消耗,这里其实是用到了享元模式,以提高空间和时间性能。
既然Integer这样设计了,其他类会不会也有呢?
接着,我又看了其他数据类型,用缓存的还不少,这里我给各位列一下,防止你们以后踩坑
基本类型 | 包装类型 | 缓存范围 |
---|---|---|
boolean | Boolean | - |
byte | Byte | -128-127 |
short | Short | -128-127 |
int | Integer | -128-127 |
long | Long | -128-127 |
float | Float | - |
double | Double | - |
小伙伴们在开发过程中,也要注意,避免掉进这个坑里。
好了,今天的分享就到这里了,如果你觉得有用,麻烦给兄弟点个小赞,这样我才更有动力去分享更多技术干货~
Recommend
-
85
原标题:掉进“网络刷单”陷阱被骗19万没挡住“高佣金”诱惑用户后悔不已并质疑腾讯企业QQ审核不严来源:IT时报IT时报记者吴雨欣“淘宝刷单兼职,只需每天晚上花打游戏的时间,就可以赚到和工资差不多的佣金!”许多人都收到过类似的兼职短信,一旦你
-
71
编者按:Nick Babich 这两年文章产量比以前低了不少,不过素质和出发点倒是一直非常发人深省。在文章结尾的 One More Thing 当中,我加入了一些...
-
55
小米上市、股价逆涨,雷军发文称“厚道的人运气不会太差”,然而不到一个月,自认厚道的小米却对米粉做了一件极为不厚道的事。 近日有米...
-
57
戒指掉进下水道口怎么办?养猫千日,用猫一时
-
18
图片来源@视觉中国 文丨歪道道 5月11日,北京OurHours全时便利店官方公众号发出一封告知函,称因公司经营战略调整,全时北京...
-
5
职场必读|98%的人会掉进这样的沟通陷阱
-
9
读者变为用户,别掉进算法的“陷阱” 来源:光明日报2021-02-20 15:05...
-
9
警惕掉进职业转型或者跳槽误区,没想到职业还有交换率非著名程序员公众号「非著名程序员」主理人,程序员/复业者/生涯规划师...
-
10
几乎每一个程序员都会走上那么一段自学的道路,尤其是在校生或进入工作岗位之后,技术的提升基本都靠自学,有的虽然是网上报班学习,但更多时候还是自己在学习,师傅引进门,修行靠个人。 有的人自学很快,几乎一个多月就能掌握一门技术,而有的人苦苦...
-
13
2个月婴儿掉进地铁轨道,多亏了一位俊杰…… ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK