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 | - |
小伙伴们在开发过程中,也要注意,避免掉进这个坑里。
好了,今天的分享就到这里了,如果你觉得有用,麻烦给兄弟点个小赞,这样我才更有动力去分享更多技术干货~
Java-Integer好大一坑,一不小心就掉进去了的更多相关文章
- 关于 Integer 的一个坑
其实 JDK 中有很多小坑, 我们稍微不注意, 就掉进去了, 然后调了半天 bug, 也不知道为何. 很闹心! 这里说一下, 在Integer中的一个小坑. 看一个小例子: @Test public ...
- Java Integer == 以及分析
Java Integer == 先看一下这段代码 Integer integer1 = 100; Integer integer2 = 100; System.out.println("in ...
- IDEA+maven+javafx(java 1.8)入坑记录
序 好久没写博客了,主要是因为懒,写博客真的是个难坚持的事.但今天登上来看了看,之前记录ctf写的wp竟然点击量这么多了,突然让我有了继续写下去的动力. 这段时间遇到了好多事,中间也有想过写几篇文章记 ...
- java integer对象判断两个数字是否相等
java integer对象判断两个数字是否相等,不一定对 问题发生的背景:javaweb的项目,起先,因为在java中实体类中的int类型在对象初始化之后会给int类型的数据默认赋值为0,这样在很多 ...
- Java web 开发填坑记 2 -如何正确的创建一个Java Web 项目
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72566261 本文出自[赵彦军的博客] Java web 开发填坑记 1-如何正确 ...
- Java Integer Cache
Java Integer Cache Java 代码 public class IntegerDemo { public static void main(String[] args) { Integ ...
- java中Integer面试的坑
class Test{ public static void main(String[] args){ //当值在[-128,127]中,不创建新的Integer Integer f1 = 100,f ...
- java中的那些坑
最近准备换工作,为了少让人家鄙视,就要狠狠地藐视这些面试题目.找了本电子书,发了有好多坑,都是特别简单,但是很少有人做对的题目.面对这样的题目,我却有一种兴奋的感觉,也许是因为一直做着重复的工作没有新 ...
- Java Integer类分析
public static final int MIN_VALUE = 0x80000000; -2^31 public static final int MAX_VALUE = 0x7ff ...
- 【转】理解Java Integer的缓存策略
本文将介绍 Java 中 Integer 缓存的相关知识.这是 Java 5 中引入的一个有助于节省内存.提高性能的特性.首先看一个使用 Integer 的示例代码,展示了 Integer 的缓存行为 ...
随机推荐
- 使用 JWT 生成 token
JWT 简介 JWT:Json Web Token 官网:https://jwt.io 优点:可生成安全性较高的 token 且可以完成时效性的检验(登陆过期检查) JWT 结构:(由官网获取) JW ...
- Windows自带管理工具
exe类notepad 记事本 control 控制面板 mstsc 远程桌面连接explorer 资源管理器 taskmgr 任务管理器resmon 资源监视器 perfmon 性能监视器reged ...
- 说一下 ArrayDeque 和 LinkedList 的区别?
大家好,我是小彭. 在上一篇文章里,我们聊到了基于链表的 Queue 和 Stack 实现 -- LinkedList.那么 Java 中有没有基于数组的 Queue 和 Stack 实现呢?今天我们 ...
- 2 c++编程-核心
重新系统学习c++语言,并将学习过程中的知识在这里抄录.总结.沉淀.同时希望对刷到的朋友有所帮助,一起加油哦! 本章是继上篇 c++编程-基础 之后的 c++ 编程-核心. 生命就像一朵花,要拼尽 ...
- JDBC Request 中 Variable names 以及 Result variable name 的使用方法
1.Variable name 的使用方法 设置好JDBC Connection Configuration.JDBC Request 具体配置百度 如果数据库查询的结果不止一列那就在Variabl ...
- Spring之SpringContext
一.概述 1.Spring Context概念 创建上下文并将BeanPostProcessor加载到spring 2.Spring Application Context概念 Spring通过应用上 ...
- 第2-4-8章 规则引擎Drools实战(1)-个人所得税计算器
目录 9. Drools实战 9.1 个人所得税计算器 9.1.1 名词解释 9.1.2 计算规则 9.1.2.1 新税制主要有哪些变化? 9.1.2.2 资较高人员本次个税较少,可能到年底扣税增加? ...
- Spring Boot回顾
一.概述 1.Spring的优缺点 优点 无需开发ELB,通过IOC和AOP,就可以使用POJO(简单的Java对象)实现ELB的功能 缺点: 依赖管理导入Maven耗时耗力 注解繁琐 2.Sprin ...
- 上传文件到阿里云 oss,前端 browser.js 笔记
Web端常见的上传方法是用户在浏览器或App端上传文件到应用服务器,应用服务器再把文件上传到OSS. 和数据直传到OSS相比,有以下缺点 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS 费用 ...
- go-carbon 1.5.0 版本发布,修复已知 bug 和新增德语翻译文件
carbon 是一个轻量级.语义化.对开发者友好的golang时间处理库,支持链式调用. 目前已被 awesome-go 收录,如果您觉得不错,请给个star吧 github:github.com/g ...