今天在学习过程中了解到一个现象,代码如下:

Integer num1 = 100;
Integer num2 = 100;
System.out.println(num1==num2?true:false);
//***********************************************
Integer num3 = 200;
Integer num4 = 200;
System.out.println(num3==num4?true:false);

这串代码,上面比较的是100装箱后比较和200装箱后比较,但是结果比较奇怪:

一个是true一个是false

首先要明确两点:

  1. Integer是包装类而不是基本数据类型,类型相比是要复杂一些的
  2. 装箱过程在编译器内进行了默认的valueOf()操作

所以该比较是比较的类,并且比较的是通过装箱操作的包装类。

回到重点,那么为什么100之间和200之间的比较完全不同?这涉及到Integer缓冲区的问题,我们可以查询一下Integer内的valueOf()方法:

    public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

解释一下这串代码,就是说装箱操作并不是简简单单就装进去就完事,其中需要判断该数i是不是满足 low <= i <= high

而缓冲区内:

int low = -128;
int high = 127;

而在这个范围,就把这个装箱后的结果取作cache数组内原有的某个结果,cache的数组区间为:

cache = new Integer[(high - low) + 1];//也就是256

譬如刚刚的例子中:

  1. 当num=100,此时判断在这个范围内,则将Integer(100)变成Integer cache[228]无论是地址还是内容都是cache[228],所以num1 == num2
  2. 当num=200,它就不在这个范围内了,那么根据函数,直接返回Integer(200),类的存储是在堆中存储的,num3,num4分别new了一个Integer,各自是不同的对象了,所以num3 !=num4

这里画一个图更容易理解,对象存储在堆中,基本类型变量存储在栈中,装箱经过从栈到堆的转换,这里创建两个100和两个200的变量进行装箱操作,示例如下:


所以结论:

当显式或者间接使用valuOf()方法时,若数值在Integer缓冲区范围内,则无论创造多少次对象都是取的缓冲区数组cache[]的原有对象,这些对象都是完全相同的;但如果不在缓冲区范围,无论创建多少次对象都是新创建的,即使内容一致也不是同一个对象。

欢迎各位提出见解

Integer缓冲区相关问题--valueOf()方法的更多相关文章

  1. 关于Integer类中parseInt()和valueOf()方法的区别以及int和String类性的转换.以及String类valueOf()方法

    Integer类中的. 关于parseInt()方法的API文档.  返回的是int类型的 关于valueOf()方法的API文档 返回的是Integer类型的. 关于intValue()方法的API ...

  2. Integer.valueOf方法的源码解读

    public class IntegerDemo { public static void main(String[] args) { Integer i01 = ; ; Integer i03 = ...

  3. js中toString和valueOf方法的区别

    toString 方法 返回对象的字符串表示形式. 语法:objectname.toString([radix]) objectname 必需.要为其搜索字符串表示形式的对象. radix 可选.为将 ...

  4. JavaScript引用类型之Array数组的toString()和valueof()方法的区别

    一.转换方法 1.在JavaScript中几乎所有对象都具有toLocaleString().toString和valueof()方法,因为,所有的对象都继承自Object,而前面所说的方法都是Obj ...

  5. java 中的valueOf方法和强转

    case1:Object 对象转String 需要强调的是String.valueOf()方法,当参数为类型是object,且值时null的时候他的处理方式 public static String ...

  6. Integer的parseInt和valueOf的区别

    先来看一下下面这段代码 String s = "1"; System.out.println(Integer.valueOf(s)); System.out.println(Int ...

  7. scanf()中清除输入缓冲区的几种方法归纳

    应用场景:我们使用多个scanf()的时候,如果输入缓冲区还有数据的话,那么scanf()就不会询问用户输入,而是直接就将输入缓冲区的内容拿出来用了,这就导致了前面的错误影响到后面的内容,为了隔离这种 ...

  8. Android随笔之——Android时间、日期相关类和方法

    今天要讲的是Android里关于时间.日期相关类和方法.在Android中,跟时间.日期有关的类主要有Time.Calendar.Date三个类.而与日期格式化输出有关的DateFormat和Simp ...

  9. JavaScript的toString()和valueof()方法

    toString()方法: 函数:函数 (function(){}).toString(); //返回"function(){}" typeof((function(){}).to ...

随机推荐

  1. 如何把 MySQL 备份验证性能提升 10 倍

    JuiceFS 非常适合用来做 MySQL 物理备份,具体使用参考我们的官方文档.最近有个客户在测试时反馈,备份验证的数据准备(xtrabackup --prepare)过程非常慢.我们借助 Juic ...

  2. Java基础(八)——IO流1_字节流、字符流

    一.概述 1.介绍 I/O是 Input/Output 的缩写,IO流用来处理设备之间的数据传输,如读/写文件,网络通讯等.Java对数据的操作是通过流的方式进行.java.io 包下提供了各种&qu ...

  3. 玩转 ByteBuffer

    为什么要讲 Buffer 首先为什么一个小小的 Buffer 我们需要单独拎出来聊?或者说,Buffer 具体是在哪些地方被用到的呢? 例如,我们从磁盘上读取一个文件,并不是直接就从磁盘加载到内存中, ...

  4. 深入理解Java虚拟机一:运行时数据区域

    根据<Java虚拟机规范(第2版)>的规定,Java虚拟机管理的内存包括下图几个运行时数据区域: 1.程序计数器        程序计数器(Program Counter Register ...

  5. 替代RTD2166|CS5212直接Pin to pin兼容替代RTD2166|替代RTD2166方案

    RTD2166功能概述 RTD2166是一款DisplayPort端口到VGA转换器,成本较高,Capstone于2019年推出CS5212,直接Pin to pin兼容替代RTD2166,可用原RT ...

  6. docker容器跨主机网络overlay

    前提:已部署好docker服务服务预计部署情况如下10.0.0.134 Consul服务10.0.0.135 host1  主机名mcw510.0.0.134 host2  主机名mcw6host1与 ...

  7. Java EE数据持久化框架 • 【第6章 MyBatis插件开发】

    全部章节   >>>> 本章目录 6.1 MyBatis拦截器接口 6.1.1 MyBais拦截器接口介绍 6.1.2 MyBais拦截器签名介绍 6.1.3 实践练习 6.2 ...

  8. Java集合与数组的联系和区别

    数组特点 存放一组相同的数据类型(基本类型和对象类型)的数据,从而实现对数据的管理. 优势:可以快速的通过下标对数组元素进行访问,效率高 劣势:容量实现定义好了,不能随着需求变化而扩容. 集合特点 集 ...

  9. ssm项目使用过滤器出现4040错误

    目录 问题 解决方法 (1)方法一 (2)方法二 问题 过滤器处理乱码问题 public class CharFilter implements Filter { @Override public v ...

  10. Hadoop集群安装(真分布式)

    Hadoop真分布式完全集群安装,基于版本2.7.2安装, 在两台Linux机器上面分别安装Hadoop的master和slave节点. 1.安装说明 不管NameNode还是DataNode节点,安 ...