遛马少年,一个代码写的很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好大一坑,一不小心就掉进去了的更多相关文章

  1. 关于 Integer 的一个坑

    其实 JDK 中有很多小坑, 我们稍微不注意, 就掉进去了, 然后调了半天 bug, 也不知道为何. 很闹心! 这里说一下, 在Integer中的一个小坑. 看一个小例子: @Test public ...

  2. Java Integer == 以及分析

    Java Integer == 先看一下这段代码 Integer integer1 = 100; Integer integer2 = 100; System.out.println("in ...

  3. IDEA+maven+javafx(java 1.8)入坑记录

    序 好久没写博客了,主要是因为懒,写博客真的是个难坚持的事.但今天登上来看了看,之前记录ctf写的wp竟然点击量这么多了,突然让我有了继续写下去的动力. 这段时间遇到了好多事,中间也有想过写几篇文章记 ...

  4. java integer对象判断两个数字是否相等

    java integer对象判断两个数字是否相等,不一定对 问题发生的背景:javaweb的项目,起先,因为在java中实体类中的int类型在对象初始化之后会给int类型的数据默认赋值为0,这样在很多 ...

  5. Java web 开发填坑记 2 -如何正确的创建一个Java Web 项目

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72566261 本文出自[赵彦军的博客] Java web 开发填坑记 1-如何正确 ...

  6. Java Integer Cache

    Java Integer Cache Java 代码 public class IntegerDemo { public static void main(String[] args) { Integ ...

  7. java中Integer面试的坑

    class Test{ public static void main(String[] args){ //当值在[-128,127]中,不创建新的Integer Integer f1 = 100,f ...

  8. java中的那些坑

    最近准备换工作,为了少让人家鄙视,就要狠狠地藐视这些面试题目.找了本电子书,发了有好多坑,都是特别简单,但是很少有人做对的题目.面对这样的题目,我却有一种兴奋的感觉,也许是因为一直做着重复的工作没有新 ...

  9. Java Integer类分析

    public static final int   MIN_VALUE = 0x80000000;  -2^31 public static final int   MAX_VALUE = 0x7ff ...

  10. 【转】理解Java Integer的缓存策略

    本文将介绍 Java 中 Integer 缓存的相关知识.这是 Java 5 中引入的一个有助于节省内存.提高性能的特性.首先看一个使用 Integer 的示例代码,展示了 Integer 的缓存行为 ...

随机推荐

  1. Helm干货!速度围观!

    最近个人学习Helm,感觉Helm的功能很强大!分享一些干货给大家吧,希望有所帮助! 基本概念 Chart 一个Helm包,包含在K8S集群内,运行一个应用,工具或者服务所需要的所有的资源定义,类似于 ...

  2. 使用vite + vue3 + ant-design-vue + vue-router + vuex 创建一个后台管理应用

    使用vite + vue3 + ant-design-vue + vue-router + vuex 创建一个管理应用的记录 使用vite 创建项目 我创建的node 版本是 v16.17.1 使用N ...

  3. K8S kubesphere安装mysql

    原先我们使用Docker按照mysql时候的命令 docker run -p 3306:3306 --name mysql-01 \ -v /mydata/mysql/log:/var/log/mys ...

  4. 【笔面试真题】ThoughtWorks-笔试-2022年1月21日

    一.选择填空判断 2n-1 二.算法题 算法题1:配对括号 算法题2:计算有效票数? 算法题3:求字符串中指定单词的数量 package com.jhliu20.real; import java.u ...

  5. 布尔值、元组、集合、input、格式化输出、赋值、运算符

    今日内容总结 目录 今日内容总结 数据类型之布尔值bool 数据类型之元组tuple 数据类型之集合set 与用户交互 1.获取输入: input 2.输出内部信息 3.在python2中与pytho ...

  6. week_3

    Andrew Ng机器学习笔记 Week_3 -- -Logistic Regression This week, we'll be covering logistic regression. Log ...

  7. 详解Python当中的pip常用命令

    原文链接:https://mp.weixin.qq.com/s/GyUKj_7mOL_5bxUAJ5psBw 安装 在Python 3.4版本之后以及Python 2.7.9版本之后,官网的安装包当中 ...

  8. Linux基础守护进程、高级IO、进程间通信

    守护进程(Daemon) 前言 Linux常用于服务器,程序通常不运行在前台.运行于前台的进程和终端关联,一旦终端关闭,进程也随之退出.因为守护进程不和终端关联,因此它的标准输出和标准输入也无法工作, ...

  9. 11、ON DUPLICATE KEY UPDATE实现插入更新操作

    一.插入与更新操作: MySQL中,采用ON DUPLICATE KEY UPDATE语句对不存在的数据进行INSERT插入操作,对已存在的数据进行UPDATE更新操作: 总结: 1.ON DUPLI ...

  10. kafka详解(04) - kafka监控 可视化工具

    kafka详解(04) - kafka监控 可视化工具 Kafka监控Eagle 1)修改kafka启动命令 修改kafka-server-start.sh命令中 if [ "x$KAFKA ...