转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10832303.html

一:基本类型与包装类型

    我们知道,Java有8大基本数据类型,4整2浮1符1布。

我们在实际开发中,除了使用到数据的值之外,还会涉及到对数据的操作。根据“面向对象”编程的思想,这些常见的操作被抽象成方法,封装到了一个类中,一个基本数据类型对应一个这样的类,这些类统称为“包装类”。

8大基本类型 分别对应 8个包装类,再加上两个用于高精度运算的包装类,共有10大包装类。分别为:

Byte:对应 byte 类型

Short:对应 short类型

Integer:对应 int类型

Long:对应 long类型

Float:对应 float类型

Double:对应 double类型

Character:对应 char类型

Boolean:对应 boolean类型

BigInteger:支持任意精度[长度]的整数运算。

BigDecmail:支持任意精度的浮点数运算,主要用于金额计算。

包装类的好处:它提供了一系列操作本类型数据的方法,可以为我们在开发过程中操作8大基本类型数据提供充足的“工具”。

二:自动拆装箱

1、装箱

把基本数据类型转换成包装类的过程就是打包装,英文名boxing,翻译为装箱。

2、拆箱

反之,把包装类转换成基本数据类型的过程就是拆包装,英文对应于unboxing,中文翻译为拆箱。

3、自动拆装箱

自动装箱: 就是将基本数据类型自动转换成对应的包装类。
    自动拆箱:就是将包装类自动转换成对应的基本数据类型。

4、自动拆装箱的发生场景

1)自动拆装箱的过程主要发生在赋值操作上:将一个基本数据类型的值符给包装类变量,则进行自动装箱操作;将一个包装类变量的值赋给基本数据类型变量,则发生自动拆箱操作。

2)将基本数据类型放入集合类时:Java中的集合类只能接收对象类型,当我们把基本数据类型放入集合类中的时候,会进行自动装箱成对应的包装类对象后再放入。

3)基本数据变量与包装类变量进行运算操作时:基本数据变量与包装类变量进行比较运算、数学运算、三目运算时,会自动拆箱成基本类型再进行运算。

4)函数返回值自动拆装箱:当函数定义时,指定了函数返回值是包装类,则return 一个基本数据类型值时,就会自动装箱;如果定义的函数返回值是基本数据类型时,return一个包装类对象会自动拆箱。

三:自动拆装箱带来的问题

1、包装对象的数值比较,不能简单的使用==,虽然-128到127之间的数字可以[下文中解释],但是这个范围之外还是需要使用equals比较。【== 比较的是地址,equals比较的是值】

2、由于自动拆箱,如果包装类对象为null,那么自动拆箱时就有可能抛出NPE[null pointer exception]。

3、如果在一个for循环中有大量拆装箱操作,会浪费很多资源。

四:Integer的缓存机制—— -128到127之间的数字自动装箱后的会返回同一个对象。

详情可参阅:Java中整型的缓存机制 这篇文章。

首先看个例子:

package com.javapapers.java;public class JavaIntegerCache {
public static void main(String... strings) { Integer integer1 = 3; //整数3自动装箱
Integer integer2 = 3; //整数3自动装箱 if (integer1 == integer2) //两个自动装箱后对象比较
System.out.println("integer1 == integer2");
else
System.out.println("integer1 != integer2"); Integer integer3 = 300;//整数300自动装箱
Integer integer4 = 300;//整数300自动装箱 if (integer3 == integer4)//两个自动装箱后对象比较
System.out.println("integer3 == integer4");
else
System.out.println("integer3 != integer4"); }}

上面的代码输出的结果是:

integer1 == integer2
integer3 != integer4

也就是说:整数3自动装箱后赋值给a、b两个引用变量,这两个引用指向的是同一个对象。

但是整数300自动装箱后赋值给c、d两个引用变量,这两个引用指向的是不同对象。

那么问题来了——都是自动装箱,为什么不同数值自动装箱的结果不一样呢?——这是由于Integer的缓存机制导致的。

1、为什么要实现Integer的缓存机制呢?

在实际开发过程中,会经常在不经意间就触发了自动拆装箱机制。我们知道,自动装箱会创建一个包装类对象,一套程序跑下来,会生成多少个这样的对象?那开销得多大啊。

因此,出于节省内存和提高性能的目的,从Java5开始,为我们提供了Integer的缓存机制。

2、Integer的缓存机制的生效逻辑

这个缓存机制是怎么工作的呢?我们来看一下Integer类的取值方法——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) {
if (i >= IntegerCache.low && i <= IntegerCache.high) //先判断整数值为是否处于IntegerCache.low~IntegerCache.high之间的缓存值
return IntegerCache.cache[i + (-IntegerCache.low)]; //是的话,则从缓存数组中取对应的包装类对象之间返回
return new Integer(i);//否,则创建一个新的包装类对象返回
}

从代码中可以看出,自动装箱时,创建对象之前先从IntegerCache.cache中寻找,如果没找到才使用new新建对象。

IntegerCache 类源码

/**
* 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 {@code -XX:AutoBoxCacheMax=} 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[]; //缓存数组 static {
// high value may be configured by property 可缓存最大值可通过jvm参数指定
int h = 127; //默认可缓存最大值为127
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); //从JVM参数中获取可缓存最大值配置
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);//将配置值与127之间取较大值,即:可缓存值最小为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(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;//断言:可缓存最大值必须大于等于127
} private IntegerCache() {}
}

从上面可以得知,Integer缓存数组中保存了 -128~h(h>=127) 的值的包装类对象,其中h值可以通过JVM参数 -XX:AutoBoxCacheMax=size 修改【这也是JVM调优的一个常用配置项】。

至于最小范围 -128~127 之间,是因为这个范围的数字是最被广泛使用的。

IntegerCache是Integer类中定义的一个private static的内部类,因此在程序中,第一次使用Integer对象的时候会需要一定的额外时间来初始化这个缓存。

3、其他包装类的缓存机制

ByteCache用于缓存Byte对象:固定范围: -128 到 127,不能更改。

ShortCache用于缓存Short对象:固定范围: -128 到 127,不能更改。

LongCache用于缓存Long对象:固定范围: -128 到 127,不能更改。

CharacterCache用于缓存Character对象:固定范围: 0 到 127,不能更改。

举个例子:

如果一个变量p的值是:

-128至127之间的整数

true 和 false的布尔值

‘\u0000’至 ‘\u007f’之间的字符

之间时,将p自动装箱成a和b两个对象,可以直接使用a==b判断a和b的值是否相等。

最新文章

  1. ios中调用友盟分享时qq可以分享但是微信失败,只显示文字,网页链接没有出现
  2. [译]Dynamics AX 2012 R2 BI系列-分析的架构
  3. ELF(Executable and Linkable Format)
  4. 对大一新生开始学习C语言课程谈几点看法
  5. HDU1004 查气球
  6. spring的声明式事务内部图
  7. Module compiled with Swift 3.0 cannot be imported in Swift 3.0.1
  8. vss的ss.ini丢失或损坏导致的vss无法登录错误
  9. php 计算一个字符串在另一个字符串中出现的次数
  10. SublimeLinter 3中使用jshint
  11. fb27a9aeaf604597826718c467cc9f4f 为什么我老收到这个
  12. scss 初学笔记 一 变量声明 默认的样式 嵌套
  13. ORACLE 数据库选择性导出表中数据&amp;导入已存在表数据
  14. iOS开发之Swift 4 JSON 解析指南
  15. Web前端学习第三天(cookie 二)
  16. 迪米特法则(Law Of Demeter)
  17. HDU 6441 - Find Integer - [费马大定理][2018CCPC网络选拔赛第4题]
  18. Linux中Postfix邮件发送配置(三)
  19. Django基础 - 修改默认SQLite3数据库连接为MySQL
  20. 导入项目出现: Unable to resolve target ‘android-10′ 解决办法

热门文章

  1. SysML——CSE 599W: Systems for ML
  2. 【oracle】ceil函数 返回值 (大于参数的最小整数)
  3. nowcoder907B n的约数
  4. 测试总结(没有rank1)
  5. Linux性能优化实战学习笔记:第四十七讲
  6. [LeetCode] 16. 3Sum Closest 最近三数之和
  7. 教你查阅Java API 英文文档(JDK 11)
  8. python实现的WebSocket客户端
  9. Django中render_to_response和render的区别(转载)
  10. 2条最佳实践App疯狂增长逻辑