我们先看一个关于Integer的例子

public static void main(String[] args) {
// TeODO Auto-generated method stu
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0); System.out.println("i1=i2\t" + (i1 == i2));
System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));
System.out.println("i4=i5\t" + (i4 == i5));
System.out.println("i4=i5+i6\t" + (i4 == i5 + i6)); System.out.println();
}
}

结果:

i1=i2     true
i1=i2+i3  true
i4=i5  false
i4=i5+i6  true

再看一个例子

public static void main(String[] args) {
// TeODO Auto-generated method stu
Integer i1 = 400;
Integer i2 = 400;
Integer i3 = 0;
Integer i4 = new Integer(400);
Integer i5 = new Integer(400);
Integer i6 = new Integer(0); System.out.println("i1=i2\t" + (i1 == i2));
System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));
System.out.println("i4=i5\t" + (i4 == i5));
System.out.println("i4=i5+i6\t" + (i4 == i5 + i6)); System.out.println();
}
}

结果

i1=i2     false
i1=i2+i3  true
i4=i5  false
i4=i5+i6  true

比较上面两个例子,我们发现:两个例子代码几乎一样,就是值不一样,40和400的区别怎么会造成如此大的结果差别呢??

我们用上篇博客的方法,用javap看他们的反编译结果

public class com.study.main.Test extends java.lang.Object{
public com.study.main.Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return public static void main(java.lang.String[]);
Code:
0: sipush 400 //40时我们用cipush(下同) cipush(char 类型)的值范围是-128——127,sipush(short 类型)的值范围是2^15——2^15-1,
3: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
6: astore_1
7: sipush 400
10: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
13: astore_2
14: iconst_0
15: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
18: astore_3
19: new #3; //class java/lang/Integer
22: dup
23: sipush 400
26: invokespecial #4; //Method java/lang/Integer."<init>":(I)V
29: astore 4
31: new #3; //class java/lang/Integer
34: dup
35: sipush 400
38: invokespecial #4; //Method java/lang/Integer."<init>":(I)V
41: astore 5
43: new #3; //class java/lang/Integer
46: dup
47: iconst_0
48: invokespecial #4; //Method java/lang/Integer."<init>":(I)V
51: astore 6
53: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
56: new #6; //class java/lang/StringBuilder
59: dup
60: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V
63: ldc #8; //String i1=i2\t
65: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
68: aload_1
69: aload_2
70: if_acmpne 77
73: iconst_1
74: goto 78
77: iconst_0
78: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la
ng/StringBuilder;
81: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;
84: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
87: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
90: new #6; //class java/lang/StringBuilder
93: dup
94: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V
97: ldc #13; //String i1=i2+i3\t
99: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
102: aload_1
103: invokevirtual #14; //Method java/lang/Integer.intValue:()I
106: aload_2
107: invokevirtual #14; //Method java/lang/Integer.intValue:()I
110: aload_3
111: invokevirtual #14; //Method java/lang/Integer.intValue:()I
114: iadd
115: if_icmpne 122
118: iconst_1
119: goto 123
122: iconst_0
123: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la
ng/StringBuilder;
126: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;
129: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
132: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
135: new #6; //class java/lang/StringBuilder
138: dup
139: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V
142: ldc #15; //String i4=i5\t
144: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
147: aload 4
149: aload 5
151: if_acmpne 158
154: iconst_1
155: goto 159
158: iconst_0
159: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la
ng/StringBuilder;
162: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;
165: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
168: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
171: new #6; //class java/lang/StringBuilder
174: dup
175: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V
178: ldc #16; //String i4=i5+i6\t
180: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
183: aload 4
185: invokevirtual #14; //Method java/lang/Integer.intValue:()I
188: aload 5
190: invokevirtual #14; //Method java/lang/Integer.intValue:()I
193: aload 6
195: invokevirtual #14; //Method java/lang/Integer.intValue:()I
198: iadd
199: if_icmpne 206
202: iconst_1
203: goto 207
206: iconst_0
207: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la
ng/StringBuilder;
210: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;
213: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
216: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
219: invokevirtual #17; //Method java/io/PrintStream.println:()V
222: return }

比较后我们惊人的发现,两者其实没有什么区别

只有这里:

0:   sipush  400 //40时我们用cipush(下同)  cipush(char 类型)的值范围是-128——127,sipush(short 类型)的值范围是2^15——2^15-1

我们看到第12行: 3:   invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int

在Integer中是调用Integer.valueOf初始化对象的

Integer.valueOf函数

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

IntegerCache

  private static class IntegerCache {
static final int high;
static final Integer cache[]; static {
final int low = -128; // high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h; cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
} private IntegerCache() {}
}

通过研究发现:Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256;Integer类中还有一个Static Block(静态块),如上所示。

从这个静态块可以看出,Integer已经默认创建了数值【-128-127】的Integer缓存数据。所以使用Integer i1=40时,JVM会直接在该在对象池找到该值的引用。

也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为40的对象,如果有直接返回该对象的引用;如果没有,则使用New keyword创建一个对象,并返回该对象的引用地址。因为Java中【==】比较的是两个对象是否是同一个引用(即比较内存地址),i2和i2都是引用的同一个对象,So i1==i2结果为”true“;而使用new方式创建的i4=new Integer(40)、i5=new Integer(40),虽然他们的值相等,但是每次都会重新Create新的Integer对象,不会被放入到对象池中,所以他们不是同一个引用,输出false。

  对于i1==i2+i3、i4==i5+i6结果为True,是因为,Java的数学计算是在内存栈里操作的,Java会对i5、i6进行拆箱操作,其实比较的是基本类型(40=40+0),他们的值相同,因此结果为True。

但是但为400时,这个时候已经超过了cache的范围,所以都得重新初始化对象

java中Integer常量池的更多相关文章

  1. 【Java_基础】java中的常量池

    1.java常量池的介绍 java中的常量池,通常指的是运行时常量池,它是方法区的一部分,一个jvm实例只有一个运行常量池,各线程间共享该运行常量池. java常量池简介:java常量池中保存了一份在 ...

  2. Java中的常量池

    JVM中有: Class文件常量池.运行时常量池.全局字符串常量池.基本类型包装类对象 常量池 Class文件常量池: class文件是一组以字节为单位的二进制数据流,在java代码的编译期间,编写的 ...

  3. Java的Integer常量池和String常量池

    1.Integer的常量池 看下面一段代码: package cn.qlq.test; public class ArrayTest { public static void main(String[ ...

  4. Java中的常量池(字符串常量池、class常量池和运行时常量池)

    转载. https://blog.csdn.net/zm13007310400/article/details/77534349 简介: 这几天在看Java虚拟机方面的知识时,看到了有几种不同常量池的 ...

  5. 19、java内存分配 常量池详解

    在class文件中,“常量池”是最复杂也最值得关注的内容. Java是一种动态连接的语言,常量池的作用非常重要,常量池中除了包含代码中所定义的各种基本类型(如int.long等等)和对象型(如Stri ...

  6. 【万字图文-原创】 | 学会Java中的线程池,这一篇也许就够了!

    碎碎念 关于JDK源码相关的文章这已经是第四篇了,原创不易,粉丝从几十人到昨天的666人,真的很感谢之前帮我转发文章的一些朋友们. 从16年开始写技术文章,到现在博客园已经发表了222篇文章,大多数都 ...

  7. Java字面常量与常量池

    Java中的字面常量(区别于final创建的有名常量)通常会保存在常量池中,常量池可以理解为像堆一样的内存区域.但是常量池有一个特性就是,如果常量池中已存在该常量将不会再次为该常量开辟内存 还是看个程 ...

  8. 第46节:Java当中的常量池

    Java当中的常量池 在Java虚拟机jvm中,内存分布为:虚拟机堆,程序计数器,本地方法栈,虚拟机栈,方法区. 程序计数器是jvm执行程序的流水线,是用来存放一些指令的,本地方法栈是jvm操作系统方 ...

  9. Java堆/栈/常量池以及String的详细详解(转)------经典易懂系统

    一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...

随机推荐

  1. 上传图片demo

    页面: js: 后台: @RequiresPermissions("pointwall:upload:edit") @RequestMapping(value = "sa ...

  2. OCR (Optical Character Recognition,光学字符识别)

    OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗.亮的模式确定其形状,然后用字符识别方法将形状翻译 ...

  3. python打造XslGenerator

    0x00前言 今天加载了Demon哥分享的RSS.其中有一篇是三好学生讲的: 在仔细越读这篇文章后,我懂得了里面的一些骚操作,所以有了以下的 脚本. 0x001代码 import optparse i ...

  4. PHP memcache client封装

    config.inc.php $CONFIG_MEMCACHE['default'] = array( //'127.0.0.1:11211:100', '10.9.20.73:11211:100', ...

  5. 关于Python安装官方whl包和tar.gz包的方法详解

    Windows环境: 安装whl包:pip install wheel -> pip install **.whl 安装tar.gz包:cd到解压后路径,python setup.py inst ...

  6. pandas入门学习--------------------------(一)

    使用pandas,首先需要熟悉它的2个主要的数据结构:Series和DataFrame. Series series是一种类似于一维数组的的对象,它由一组数据(各种Numpy数据类型)以及一组与之相关 ...

  7. 「小程序JAVA实战」springboot的后台搭建(31)

    转自:https://idig8.com/2018/08/29/xiaochengxujavashizhanspringbootdehoutaidajian31/ 根据下面的图,我们来建立下对应的sp ...

  8. 关于Web项目出现懒加载异常的解决方案

    manytomany关系中,使用 fetch = FetchType.LAZY 来做懒加载,加快些性能.但是却一直出错,原因是session被关闭,要保持session,需要事务. Hibernate ...

  9. AMF_OBJECT 数据结构浅析

    组织的比较散,主要是标记一下有关 AMF_OBJECT 数据组织结构.其标识嵌套结束则为 0x 00 00 09 原始数据结构已知: key=“0123456”: Value 的值是一个结构体如下: ...

  10. LUA 环境

    LUA中环境是指一个函数执行的表,即一个函数在什么表中执行. 这里的函数是特殊的,是loadfile("x.lua")的返回值. loadfile("x.lua" ...