在上篇《java的自动拆箱会发生NPE》博客中接收了java中的Integer中的自动拆箱产生的NPE,其实对于所有的包装类来说都是一样的,都会产生这样的问题,大家需要举一反三,做学问学知识要懂得反思总结。

一、前情回顾

先回顾下上次的知识点,

自动拆箱 实际调用的是intValue()方法

自动装箱 实际调用的是valueOf(int i)方法

其他的包装类,小伙伴们自己总结

二、Integer的本地缓存

好了话不多说,书接上回,开始这次的分享,上次说到在自动装箱的时候还大有玄机,这个玄机就是本地缓存。这个玄机在自动装箱的方法中,如下

/**
* 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) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

先看下其方法说明吧,用我大学英语六级的水平给大家翻译下,献丑了大家莫怪,

返回一个代表指定int的Integer对象,如果一个新的Integer实例不是必需的,这个方法通常使用构造方法来生成,另一方面,这个方法通常为了节省空间和实际会缓存一些经常使用的值

这个方法会缓存[-128~127]间的值,也可能会缓存这个范围以外的值

翻译的太差劲了,大体意思是如果参数在[-128,127]间则会从缓存中取,如果不在则直接生成Integer的实例。还有很重要的一点最大值可以配置。

看方法的逻辑也是这样的,看下Integer初始化缓存的代码,在Integer中有静态内部类IntegerCache,代码

private static class IntegerCache {
//缓存区间,最小值
static final int low = -128;
//缓存区间,最大值,可配置
static final int high;
//缓存
static final Integer cache[]; static {
// high value may be configured by property
int h = 127;
//获得配置的缓存区间最大值
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h; cache = new Integer[(high - low) + 1];
int j = low;
//for循环,生成缓存
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
} private IntegerCache() {}
}

上面的代码加注释足以说明一切,不再一一解释了,默认情况下Integer中存在[-128,127]范围内的的256个缓存Integer实例。

三、验证本地缓存

上面说到,在Integer中存在缓存,重要的一点是在调用valueOf()方法的时候才会校验缓存,valueOf方法共有以下几个

重要声明,在使用构造方法的时候是没有缓存的,看构造方法

 /**
* Constructs a newly allocated {@code Integer} object that
* represents the specified {@code int} value.
*
* @param value the value to be represented by the
* {@code Integer} object.
*/
public Integer(int value) {
this.value = value;
}

那么在验证的时候就不能使用构造方法的方式,需要使用自动装箱的方式。

1、构造方法没有缓存

public class TestIntegerConstruct {
public static void main(String[] args) {
Integer i1=new Integer(1);
Integer i2=new Integer(1);
System.out.println(i1==i2); }
}

打印结果为,

false

Process finished with exit code 0

打印出来为false,说明i1和i2为两个不同的对象。

2、valueOf()方法才有的缓存

使用valueOf构造两个Integer对象,

public class TestValueOf {
public static void main(String[] args) {
Integer i1=1;
Integer i2=1;
System.out.println(i1==i2);
}
}

打印结果为,

true

Process finished with exit code 0

说明i1和i2为同一个实例,这里使用的是==来判断,对引用对象来说判断的不正是其地址。

多说一点,这里两个引用类型的比较,大家不要像我这里似的,使用“==”,请使用equals方法,使用“==”比较的是内存地址,在大部分情况下,内存地址肯定不相等,而使用equals方法就说不准了,equals方法比较的是什么?

3、Integer的equals方法

看下Integer的equals方法比较的是什么东西

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

看到没,搜先判断的是类型,然后调用其intValue方法,也就是拆箱,比较的是Integer中value的值,也就是数值的比较。

四、总结

本文,分享了Integer中的本地缓存,需要明白以下几个问题,

1、什么时候会用到本地缓存?--调用valueOf方法的时候

2、本地缓存的大小;--默认为[-128,127],最大值可设置

3、equals方法比较的是什么;--比较的是值得大小,非内存地址

往期推荐

java的自动拆箱会发生NPE

源码中的设计模式--单例模式

java的Integer中也会有缓存的更多相关文章

  1. 谈谈Integer中的静态类IntegerCache

            学习的本质就是一个赋值的过程,用新知识来覆盖你的旧知识或者无知(null).掌握知识是自己的, 分享知识,才能帮助更多的人,创造更大的价值.学贵以恒,以此自勉,与君共享.----曦阳X ...

  2. 【JDK】:java.lang.Integer源码解析

    本文对JDK8中的java.lang.Integer包装类的部分数值缓存技术.valueOf().stringSize().toString().getChars().parseInt()等进行简要分 ...

  3. Integer 中的缓存类IntegerCache

    2014年去某公司笔试的时候遇到这么一道题: public class Test { public static void main(String[] args) { Integer int1 = I ...

  4. Java之戳中痛点 - (7)善用Java整型缓存池

    先看一段代码: package com.test; import java.util.Scanner; public class IntegerCache { public static void m ...

  5. Java自动装箱中的缓存原理

    今天看到一道'经典'面试题: Integer a = 100; Integer b = 100; System.out.println(a==b); Integer a2 = 200; Integer ...

  6. 对Integer类中的私有IntegerCache缓存类的一点记录

    对Integer类中的私有IntegerCache缓存类的一点记录 // Integer类有内部缓存,存贮着-128 到 127. // 所以,每个使用这些数字的变量都指向同一个缓存数据 // 因此可 ...

  7. Java Integer中的IntegerCache小记

      同事今天给我发了一个关于Java拆装箱的ppt,里面有这么一段代码 Integer c = Integer.valueOf(3); Integer d = Integer.valueOf(3); ...

  8. Integer 中的缓存类 IntegerCache

    我们先看一段代码: public class TestAutoBoxing { public static void main(String[] args) { //-128到127之间 Intege ...

  9. Java.lang.Integer类中toString(int i, int radix)的具体实现

    Java.lang.Integer.toString(int i,int radix)方法可以实现将一个int类型的10进制的数据转换为指定进制的数据. api文档中介绍: 返回第二个参数指定的基数中 ...

随机推荐

  1. python监控cpu 内存实现邮件微信报警

    # qianxiao996精心制作 #博客地址:https://blog.csdn.net/qq_36374896 import psutil, time,smtplib,socket import ...

  2. Axure7.0 以及 中文汉化语言包下载 axure汉化包

    支持 Axure RP Pro 正式版 当前最新版本 7.0.0.3184 不兼容6.5及以下版本! Axure7.0 下载地址:http://pan.baidu.com/s/1dEuR8YX Axu ...

  3. Python库国内镜像

    中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ http://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣 http://py ...

  4. 那么回到我们开始的问题,通常一棵B+树可以存放多少行数据?

    这里我们先假设B+树高为2,即存在一个根节点和若干个叶子节点,那么这棵B+树的存放总记录数为:根节点指针数*单个叶子节点记录行数. 上文我们已经说明单个叶子节点(页)中的记录数=16K/1K=16.( ...

  5. 为什么 wait 和 notify 方法要在同步块中调用?

    Java API 强制要求这样做,如果你不这么做,你的代码会抛出 IllegalMonitorStateException 异常.还有一个原因是为了避免 wait 和 notify 之间产生竞态条件.

  6. 在 java 中守护线程和本地线程区别?

    java 中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法 Thread.setDaemon(bool on):true 则把该线程 ...

  7. Zookeeper 文件系统 ?

    Zookeeper 提供一个多层级的节点命名空间(节点称为 znode).与文件系统不 同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放 数据而目录节点不行. Zookeeper ...

  8. 定时任务__@Xxl-JOB的使用

    概述xxl-job框架 ​ 首先我们要知道什么是XXL-JOB? ​ 官方简介:XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码并接入多家公司 ...

  9. 数字电路基础知识——组合逻辑电路(数据选择器MUX、多路复用器)

    转自:https://blog.csdn.net/vivid117/article/details/100747939 数字电路基础知识--组合逻辑电路(数据选择器MUX.也即多路复用器)本次介绍数据 ...

  10. Slog71_选取、上传和显示本地图片GET !(微信小程序之云开发-全栈时代3)

    ArthurSlog SLog-71 Year·1 Guangzhou·China Sep 12th 2018 ArthurSlog Page GitHub NPM Package Page 掘金主页 ...