JavaStudy——Java之自动拆箱与自动装箱
java基本类型介绍
java中,基本数据类型一共有8种,详细信息如下表:
类型 | 大小 | 范围 | 默认值 |
byte | 8 | -128 - 127 | 0 |
short | 16 | -32768 - 32768 | 0 |
int | 32 | -2147483648-2147483648 | 0 |
long | 64 | -9233372036854477808-9233372036854477808 | 0 |
float | 32 | -3.40292347E+38-3.40292347E+38 | 0.0f |
double | 64 | -1.79769313486231570E+308-1.79769313486231570E+308 | 0.0d |
char | 16 | \u0000 - u\ffff | \u0000 |
boolean | 16 | true/false | false |
Java语言是一种面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,设计者将每个基本数据类型单独封装成一个类,这八个和基本数据类型对应的类统称为包装类(Wrapper Class)。
1.什么是自动拆箱与自动装箱
自动装箱:把基本类型用它们对应的包装类包装起来,使它们具有对象的特质,可以调用所对应的包装类所定义的方法,比如toString()等。
举个例子:
Integer i0 = new Integer(0);
Integer i1 = 2;
Integer i1_ = Integer.valueOf(2);
上面的三行代码第一行是最基本的创建一个integer对象的方式。第二行代码就是我们这里要讲的自动装箱。而第三行代码就是第二行代码的本质,也就是说,当你使用自动装箱来得到一个引用数据类型时,jvm实际上调用了valueOf()方法,稍后我们会去研究一下java源码。
自动拆箱:跟自动装箱的方向相反,将Integer及Double这样的包装类的对象重新简化为基本类型的数据。
举个例子:
1.System.out.println(i1+2);
这句代码就使用了自动拆箱。i1是我们上面通过自动装箱得到的一个integer对象,而这个对象是不能直接进行四则运算的,但是我们却给它+2,这样就必须将integer对象转变为基本数据类型(int),这个过程就是自动拆箱的过程。
p.s.所谓自动,就是说这个过程并不需要程序员去完成,而是jvm自动完成的,jvm会在编译期根据语法决定是否进行装箱和拆箱动作。
另外,自动拆箱与自动装箱的jdk1.5才引入的新特性,所以如果你的jdk版本低于1.5的话,是不可以这样写的。
2.为什么会有自动拆箱与自动装箱
为什么java要提供这样一个功能呢?我的理解是这样的:
1.因为懒。假如没有自动拆箱与自动装箱,那么我们的代码是这样的:
Integer i = new Integer(2);//假如需要一个integer的对象i,值为2
int b=i.intValue();//又需要一个int型的值,大小与i相等
- 1
- 2
但是,有了自动拆箱与装箱,我们就可以这么写:
Integer i = 2;
int b = i;
是不是省了不少事,而且看起来代码更简洁了呢?
2.自动装箱的过程其实可以起到节约内存的作用。我们先看一个例子:
Integer a = 1;
Integer b = 1;
Integer c = 144;
Integer d = 144;
Integer a1 = new Integer(1);
Integer b1 = new Integer(1);
System.out.println(a == b); //true
System.out.println(a.equals(b)); //true
System.out.println(a1 == b1); //false
System.out.println(a1.equals(b1)); //true
System.out.println(c == d); //false
System.out.println(c.equals(d)); //true
是不是很奇怪,为什么第7行为true而第12行为false呢?这是因为,在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象 。而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。
那么,为什么要这么设计呢?一般来说,小数字的使用频率很高,将小数字保存起来,让其始终仅有一个对象可以节约内存,提高效率。
这其实用到了一种叫做享元模式的设计模式,感兴趣的可以去研究一下这个设计模式。
3.怎么使用自动拆箱与自动装箱
使用方式通过上面的例子大家应该也都清楚了,自动拆箱与装箱实际上就是jvm帮我们去调用一些函数,这样可以使我们省不少事,代码也会看起来更简洁一些,不过在这里还有一点需要强调,先看代码:
Integer a = null;
int b = a;
这么写完全是符合java语法规范的,编译也可以正常通过,但是很明显,运行的时候回抛出空指针异常。所以在这里提醒大家,在使用自动拆箱时,一定要确保包装类的引用不为空。
4.源码剖析
上面提到了几个包装类的方法,我们一Integer类为例,来看一看java源码是什么样子的。首先是valueOf()方法:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
// 没有设置的话,IngegerCache.high 默认是127
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
上面讲到,在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用。现在明白是为什么了吧,在调用valueOf()方法的时候,会判断你所给的数是不是在IntegerCache.low 和 i <= IntegerCache.high之间,如果是,那么他就在内存中生成唯一的对象,当你第二次想要生成它的时候,他会把第一次所生成对象的地址给你,不会重新生成。而不在这个范围里的数,你每次所生成的对象都是不同的。
自动装箱池的大小是怎么定义的呢,Integer.java中有这样一个内部类
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(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() {}
}
IntegerCache类(这个是jdk1.8的源码)定义了Integer自动装箱池的大小。从源码中我们可以看到,下界是写死的,就是-128,但是上界却是由参数integerCacheHighPropValue解码得来的,这就表明,其实我们可以通过改变integerCacheHighPropValue值的大小来自定义自动装箱池的大小,当然,一般没人会去改它。
Integer自动装箱池的范围是-128~127
Byte,Short,Long范围是-128~127
Character范围是0~127
Float和Double没有自动装箱池
5.总结
Java通过自动装箱和拆箱的机制,节省了部分内存开销和创建对象的开销,提高了效率同时简化了代码。在使用该机制的时候,需要注意以下几点:
1.在进行==比较的时候,在自动装箱池范围内的数据的引用是相同的,范围外的是不同的。
2。在自动拆箱时,要保证包装类的引用不为空。
JavaStudy——Java之自动拆箱与自动装箱的更多相关文章
- Java进阶之自动拆箱与自动装箱
序. java基本类型介绍 java中,基本数据类型一共有8种,详细信息如下表: 类型 大小 范围 默认值 byte 8 -128 - 127 0 short 16 -32768 - 32768 0 ...
- 如何理解Java中的自动拆箱和自动装箱?
小伟刚毕业时面的第一家公司就被面试官给问住了... 如何理解Java中的自动拆箱和自动装箱? 自动拆箱?自动装箱?什么鬼,听都没听过啊,这...这..知识盲区... 回到家后小伟赶紧查资料,我透,这不 ...
- 享元模式(FlyWeight Pattern)及其在java自动拆箱、自动装箱中的运用
本文主要从三个方面着手,第一:简要介绍享元模式.第二:享元模式在基本类型封装类中的运用以Integer为例进行阐述.第三:根据第一.第二的介绍,进而推出java是如何实现自动拆箱与装箱的. 第一:简要 ...
- Java语法糖2:自动装箱和自动拆箱
前言 一开始想学学自动拆箱和自动装箱是被这个名字吸引到,听上去好像很高端的样子,其实自动拆箱.自动装箱是很简单的内容. 自动拆箱和自动装箱 Java为每种基本数据类型都提供了对应的包装器类型.举个例子 ...
- java 自动装箱自动拆箱
1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference ...
- 转!!Java学习之自动装箱和自动拆箱源码分析
自动装箱(boxing)和自动拆箱(unboxing) 首先了解下Java的四类八种基本数据类型 基本类型 占用空间(Byte) 表示范围 包装器类型 boolean 1/8 true|fal ...
- java 自动装箱和自动拆箱
自动装箱 java执行Integer i = 100:编译器编译成Integer i = Integer.valueOf(100); Integer i = 100; //编译器编译成Integer ...
- Java中的自动拆箱装箱(Autoboxing&Unboxing)
一.基本类型打包器 1.基本类型:long.int.double.float.boolean 2.类类型:Long.Integer.Double.Float.Boolean 区别:基本类型效率更高,类 ...
- 别说你不知道java中的包装类,wrapper type,以及容易在自动拆箱中出现的问题
很多时候,会有人问你,你知道什么是包装类吗? 或者高端一点问你你知道,wrapper type,是什么吗? 然后你就懵逼了,学了java很多时候都不知道这是啥. 其实问你的人,可能只是想问你,java ...
随机推荐
- 一个数组中两个数的和为N,找出这两个数字的下标
分析,两个数字的和为N.那么这两个数字是否是唯一的呢?输出的下标是否是第一对出现的呢? 1,我们假设这两个数字是唯一的 和是唯一的,那么其中一个数字越大,另一个数字就越小.想到大小关系,我们就想到了排 ...
- Mysql5.7出现this is incompatible with sql_mode=only_full_group_by
vi /etc/my.cnf #编辑mysql配置文件 在 [mysqld]和[mysql]下添加 sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZE ...
- HBuild 连接苹果手机
PC.苹果手机.数据线 1.在电脑端安装iTunes,安装完成之后提示重启. 2.用数据线连接苹果手机 PC 3.打开HBuild 菜单栏 --> 运行 --> 真机 ...
- MySQL自增序列-亲试ok
#1.创建sequence表,公共的 DROP TABLE IF EXISTS sequence; CREATE TABLE sequence ( name VARCHAR(30) NOT ...
- MapRedcue的demo(协同过滤)
MapRedcue的演示(协同过滤) 做一个关于电影推荐.你于你好友之间的浏览电影以及电影评分的推荐的协同过滤. 百度百科: 协同过滤简单来说是利用某兴趣相投.拥有共同经验之群体的喜好来推荐用户感兴趣 ...
- 【转】阿里云免费SSL证书申请与安装使用(IIS7)
阅读目录 准备: 第一步:免费SSL证书申请 第二步:证书导入 第三步:分配服务器证书 最后一步:访问测试 回到顶部 准备: 阿里云已完成备案的域名一个 回到顶部 第一步:免费SSL证书申请 登陆阿里 ...
- Eclipse调试多线程代码
Eclipse调试多线程代码 标签: eclipse 调试 多线程 | 发表时间:2013-02-16 05:51 | 作者:czjuttsw 分享到: 出处:http://blog.csdn.net ...
- Jumpserver跳板机的搭建和部署
1.需要搭云yum仓库wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo 2. ...
- vue-router进阶-1-导航守卫
导航守卫主要用来通过跳转或取消的方式守卫导航 全局守卫,使用 router.beforeEach 注册一个全局前置守卫 const router = new VueRouter({ ... }) ro ...
- C#中用NPOI的excel导出
//机构表导出 private static List<User2> amininf = new BLL.Bll().GetUser2s(); //定义数据源导出对象 #region 导出 ...