当前位置: 首页 > news >正文

Java数据类型(2)------自动封装拆箱

目的:

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

定义:

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型byte,short,char,int,long,float,doubleboolean对应的封装类为Byte,Short,Character,Integer,Long,Float,Double,Boolean

实现:

自动装箱时编译器调用valueOf将原始类型值转换成对象,同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成原始类型值。

发生时间:

有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么Java会自动讲这个原始类型值转换成与之对应的对象。

List<Integer> list = new ArrayList<Integer>();

// 自动装箱

list.add(1);

list.add(2);

// 拆箱

int i = list.get(0);

int ii = list.get(1);

自动装箱的弊端:

自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

Integer sum = 0;

 for(int i=1000; i<5000; i++){

   sum+=i;

}

上面的代码sum+=i可以看成sum = sum + i,但是==+-*/这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其过程如下

int temp = sum.intValue() + i;

Integer sum = new Integer(temp);

由于我们这里声明的sumInteger类型,在上面的循环中会创建将近5000个无用的Integer对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题.

注意事项:

  自动装箱和拆箱可以让代码简洁,但是,我们在使用的时候应该注意下,否则会发生一些问题。

1.比较

”==“可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,即检查引用地址是否相同。这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==“,而应该使用对象对应的equals方法

// 1

int i1=1;

int i2=1;

System.out.println(i2==i1);// true

// 2

Integer I1=1;

System.out.println(I1==i1);// true

Integer I2=1;

System.out.println(I1==I2);// true

// 3

Integer I3 = 128;// 触发自动封装

Integer I4 = 128;

System.out.println(I3==I4);// false

// 4

Integer I5= new Integer(1);// 不触发自动封装

Integer I6= new Integer(1);

System.out.println(I5==I6); // false

值得注意的是第2个小例子的第二个比较,这是一种极端情况。I1和I2的初始化都发生了自动装箱操作。但是处于节省内存的考虑,JVM会缓存-128到127的Integer对象。因为I1和I2实际上是同一个对象。所以使用”==“比较返回true,而第三个小例子使用‘==’返回false

注:自动封装的函数

public static Integer valueOf(int i) {

 return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];

 }

private static final Integer[] SMALL_VALUES = new Integer[256];

2.容易混乱的对象和原始数据值

另一个需要避免的问题就是混乱使用对象和原始数据值,一个具体的例子就是当我们在一个原始数据值与一个对象进行比较或赋值时,如果这个对象没有进行初始化或者为Null,在自动拆箱过程中obj.xxxValue,会抛出NullPointerException,如下面的代码

private static Integer count;

if(count>=0){

System.out.println(11111111111L);

}

3.缓存的对象

Java中,会对-128到127的Integer对象进行缓存,当创建新的Integer对象时,如果符合这个这个范围,并且已有存在的相同值的对象,则返回这个对象,否则创建新的Integer对象。

4.生成无用对象

因为自动装箱会隐式地创建对象,像前面提到的那样,如果在一个循环体中,会创建无用的中间对象,这样会增加GC压力,拉低程序的性能。所以在写循环时一定要注意代码,避免引入不必要的自动装箱操作。

转载于:https://www.cnblogs.com/zuiwoshanlin/p/7067228.html

相关文章:

  • Java实现排序算法(一)
  • JMS 之 Active MQ 的spring整合
  • Java实现排序算法(二)
  • vue项目实战爬坑小记001
  • Java实现排序算法(三)
  • Java通信编程之Socket入门
  • 回车提交表单
  • 数据库的查询优化技术
  • 微信jssdk分享功能,jssdk成功调用,分享内容自定义失败
  • 用VS2005制造WEB安装程序
  • Java对象实例化顺序
  • 非阻塞模式下,虽然connect出错,但是getsockopt取得的错误却是0的问题
  • Java面试之判断对错
  • PL/SQL
  • 数据库系统优化--业务逻辑设计优化
  • python3.6+scrapy+mysql 爬虫实战
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 11111111
  • canvas 绘制双线技巧
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • export和import的用法总结
  • leetcode讲解--894. All Possible Full Binary Trees
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Spring声明式事务管理之一:五大属性分析
  • Vue实战(四)登录/注册页的实现
  • Xmanager 远程桌面 CentOS 7
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 第十八天-企业应用架构模式-基本模式
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 算法系列——算法入门之递归分而治之思想的实现
  • 突破自己的技术思维
  • 学习ES6 变量的解构赋值
  • MyCAT水平分库
  • 第二十章:异步和文件I/O.(二十三)
  • ​ubuntu下安装kvm虚拟机
  • # 透过事物看本质的能力怎么培养?
  • #WEB前端(HTML属性)
  • (1)Nginx简介和安装教程
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (bean配置类的注解开发)学习Spring的第十三天
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (一)u-boot-nand.bin的下载
  • .net wcf memory gates checking failed
  • .net 设置默认首页
  • .NET 依赖注入和配置系统
  • .net对接阿里云CSB服务
  • .net获取当前url各种属性(文件名、参数、域名 等)的方法
  • .NET简谈设计模式之(单件模式)
  • .net连接oracle数据库
  • .net知识和学习方法系列(二十一)CLR-枚举
  • @Query中countQuery的介绍
  • @RequestMapping用法详解