背景和问题

  在看别人整理的资料时,看到如下一段代码:

package com.sitech.test;
/**
* 自动装箱和拆箱 jdk1.6
* @author liaowp
*
*/
public class TestInteger { public static void main(String[] args) {
Integer i1 = 80, i2 = 80, i3 = 999, i4 = 999;
System.out.println(i1 == i2);//true
System.out.println(i3 == i4);//false
}
}

  如果没有看过源码的同学肯定觉的答案要么是2个true要么是2个false。我刚看到这一段代码的时候也觉的是2个true,感觉自己100%确定,不过真正运行之后才发现傻眼了,一个true一个false,这是Bug吧。其实LZ以前看过一部分Integer源码了,但是现在想想好像看的不认真,尴尬了。于是被这个问题触发了LZ要认真看一次Integer源码了(我要认真了,哈哈)。

  我们还是回到上面那个问题吧,先把问题解决了在吹nb。我们可以看到上面的代码4个变量都是Integer的引用,所以输出的==运算比较的不是Integer值而是Integer引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,我们看一看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
*/
public static Integer valueOf(int i) {//是一个静态方法 IntegerCache是一个内部类
assert IntegerCache.high >= 127;//断言 参考http://lavasoft.blog.51cto.com/62575/43735/
if (i >= IntegerCache.low && i <= IntegerCache.high)//如果i大于对于IntegerCache.low()且i小于等于IntegerCache.high
return IntegerCache.cache[i + (-IntegerCache.low)];//直接从缓存取出来
return new Integer(i);//新创建一个Integer对象
}

  从上面的代码中我们可以看出Integer维持了一个缓存系统,如果在缓存的范围内直接取出来就好了,如果不在的就要创建新的Integer对象。但是具体缓存范围是什么的,我们在深入进去看看:

    /**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the -XX:AutoBoxCacheMax=<size> option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/ private static class IntegerCache {//静态类哦
static final int low = -128;//最小值是-128
static final int high;//最高
static final Integer cache[];//缓存数组 这三个都final,不可修改的 static {//静态代码块 静态代码块会比改造方法先执行
// high value may be configured by property
int h = 127;//默认的
String integerCacheHighPropValue =//定义一个String
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");//取得设置的值
if (integerCacheHighPropValue != null) {//如果设置了就用设置的值
int i = parseInt(integerCacheHighPropValue);//把String转换为int
i = Math.max(i, 127);//获得i和127的更大的一个,其实是不能小与默认的
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low));//如果取的小的那个,不能超过Integer的最大值+low
}
high = h;//最大值为127 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的缓存

  看完之后我相信基本都知道为啥一开始的那一段代码会这样了,我现在做一个小的总结,Integer里面有一个内部类IntegerCache,是用来做缓存优化性能的。默认缓存了-128到127中间的数字,据说这些使的比较频繁。其实java里面好多的类都有这样的优化。如果在-128-127之间的就直接拿缓存的,不在的就new一个Integer。所以这也就解释了上面的那个问题了嘛

  本来还想把整个类都分析一遍的,后面看了看别人的分析的发现自己在的分析已经作用不大了,如果想往完整的看Integer类的分析,LZ推荐http://www.cnblogs.com/vinozly/p/5173477.html

由自动装箱和拆箱引发我看Integer源码的更多相关文章

  1. Java 自动装箱与拆箱

    Java 自动装箱与拆箱(Autoboxing and unboxing)   什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供 ...

  2. 《Java中的自动装箱和拆箱功能.》

    //Java中的自动装箱和拆箱功能. class AutoboxingUnboxing { public static void main(String[] args) { //直接把一个基本类型变量 ...

  3. 【转】java 自动装箱与拆箱

    java 自动装箱与拆箱 这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的 ...

  4. 深入剖析Java中的自动装箱和拆箱过程

    深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱 ...

  5. Java中的自动装箱与拆箱

    自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动地转换成对应的对象.自动装箱与拆箱的机制可以让我们在Java的变量赋值或者是方法调用等情况下使用原始类型或者对象类型更加简单直接. 如 ...

  6. Java自动装箱和拆箱

    jdk5.0之后,在基本数据类型封装类之间增加了自动装箱和拆箱的功能,其实“自动”的实现很简单,只是将装箱和拆箱通过编译器,进行了“自动补全”,省去了开发者的手动操作. 而进行封装类与对应基本数据类型 ...

  7. [转]JAVA自动装箱和拆箱

    http://www.cnblogs.com/dolphin0520/p/3780005.html 1.Java数据类型 装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类 ...

  8. Java进阶(三十七)java 自动装箱与拆箱

    Java进阶(三十七)java 自动装箱与拆箱 前言 这个是jdk1.5以后才引入的新的内容.java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装称为装箱,解包装称为 ...

  9. java -关于包装类自动装箱与拆箱拓展+整形常量池

    关于自动装箱与拆箱 1.包装类与基本数据类型的自动转换,叫装箱和拆箱(类型自动转换) 2.自动装箱拆箱是在编译器,编译器自动配转换方法,实现装箱和拆箱.所以这个过程发生在编译期 3.只有需要相互类型转 ...

随机推荐

  1. 一步一步写算法(之n!中末尾零的个数统计)

    原文:一步一步写算法(之n!中末尾零的个数统计) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在很多面试的题目中,求n!结果中零的个数也是 ...

  2. 6. SQL Server数据库监控 - 如何告警

    原文:6. SQL Server数据库监控 - 如何告警 常用的告警方式大致有:短信.邮件.应用程序 (beep提示,图标提示,升窗提示等),可是不能一直坐在电脑前看着应用程序,或者用脚本部署监控,根 ...

  3. 多线程下HashMap的死循环是如何产生的

    前言 HashMap不是线程安全的,如果需要在多线程环境中使用Map,那么我们可以使用ConcurrentHashmap. 1.举例说明: package com.test; import java. ...

  4. 因下面文的损坏或丢失windows/system32/config/system 解决方法

    这是因为你电脑的初始化文件遭破坏所致.导致破坏的原因也可能是病毒或其它原因. 因为Windows启动须要读取Syatem.ini,Win.ini和注冊表文件,假设C盘根文件夹下有config.sys, ...

  5. POJ3187 Backward Digit Sums

    给出杨辉三角的顶点值,求底边各个数的值.直接DFS就好了 #include<iostream> #include<cstdio> #include<cstring> ...

  6. at System.Data.EntityClient.EntityConnection.GetFactory(String providerString)

    最近在做一个WinForm的项目. 使用vs2013开发. 数据库使用的是oracle. 在本地写了一个webservice .测试正常.发布到服务器的时候.就是提示了错误. 打开服务器上的日志.看到 ...

  7. Android在View拉丝工艺和invalidate()和其他相关方法

      转载请注明出处:http://blog.csdn.net/qinjuning 前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 . ...

  8. C#边边角角(一)

    前言 此篇为在学习C#基础时,熟悉C#的语法和高级特性的一些小的尝试和笔记,记录一下以供分享 集合初始化器 集合必须实现System.Collections.IEnumerable接口 集合必须包含A ...

  9. 松瀚SN8P2711 2722 ADC初始化程序及应用--汇编源码

    /* 松瀚 SN8P2711 2722 ADC初始化程序 及应用实例 */ INIT_ADC: MOV A, #0XB2 // 启动ADC电路 使能AIN通道 B0MOV ADM, A MOV A,# ...

  10. iOS基础 - NSURLSession

    使用URLSession所有的网络访问都是有缓存的,缓存文件自动保存在tmp文件夹中,URLSession本身实现的时候,就是少量多次的! l 使用defaultSessionConfiguratio ...