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 的缓存行为 ...
随机推荐
- jvm双亲委派机制详解
双亲委派机制 记录一下JVM的双亲委派机制学习记录. 类加载器种类 当我们运行某一个java类的main方法时,首先需要由java虚拟机的类加载器将我们要执行的main方法所在的class文件 ...
- SpringCloudAlibaba 微服务组件 Nacos 之配置中心源码深度解析
大家好,这篇文章跟大家聊下 SpringCloudAlibaba 中的微服务组件 Nacos.Nacos 既能做注册中心,又能做配置中心,这篇文章主要来聊下做配置中心时 client 端的一些设计,主 ...
- windows安装nodejs
安装nodejs 1.官网地址: http://nodejs.cn/download 2.选择下载路径 直接无脑下一步安装 3.安装成功之后 node -v 显示nodejs版本 npm -v 显示安 ...
- EntityFramework介绍
首先我们说明一下ORM是什么. 微软官方提供的ORM工具,ORM让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上.开发人员使用Linq语言,对数据库操作如同操作Object对象 一 ...
- day02-实现01
实现01 1.实现任务阶段1 编写mytomcat,该服务器能给浏览器返回"你好,我是服务器!"的简单信息. 根据之前的tomcat框架整体分析,我们将浏览器发送请求,tomcat ...
- Linux内存泄露案例分析和内存管理分享
作者:李遵举 一.问题 近期我们运维同事接到线上LB(负载均衡)服务内存报警,运维同事反馈说LB集群有部分机器的内存使用率超过80%,有的甚至超过90%,而且内存使用率还再不停的增长.接到内存报警的消 ...
- Android开发之应用更新或软件下载
Android开发之应用更新或软件下载 本文章学习前提:okHttp3或以上,EventBus或其它事件总线工具,四大组件的Activity和Service,安卓通知基础知识 新建项目文件 目录结构如 ...
- OSI传输层TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念
目录 传输层之TCP与UDP协议 应用层 socket模块 socket基本使用 代码优化 半连接池的概念 传输层之TCP与UDP协议 TCP与UDP都是用来规定通信方式的 通信的时候可以随心所欲的聊 ...
- Fastjsonfan反序列化(一)
前置知识 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象. Fastjson 可以操作任何 Java 对象 ...
- JavaScript笔记基础
JavaScript合集 学完HTML5+CSS3的小伙伴,学习JS时,要多敲多练多想多拓展 刚开始入门JS的时候,我们不需要纠结那么多,有些需要先记住,后面会慢慢明白为什么是这样的 JS基础部分 我 ...