当前位置: 首页 > 科技观察

深入理解Java的装箱和拆箱

时间:2023-03-21 16:12:54 科技观察

一、Java的数据类型1、在说装箱和拆箱之前,先说说Java的基本数据类型。Java从数据类型上可以分为值类型和引用类型,值类型有四种类型和八种类型,分别是:整数类型:byte?、short?、int?、long浮点类型:float、double字符类型:charBooleantype:boolean数据类型memory默认值packagingclassbyte8bits0Byteshort16-bit0shortint32-bit0Integerlong64-bit0Lor0lLongfloat32-bit0.0For0.0fFloatdouble64-bit0.0D或0.0dDoublechar16-bit\u0000Characterboolean8-bitflaseBoolean2.引用类型:数组类(class)接口(Interface)枚举(enum)3.值类型和引用类型的区别1.概念上:值类型:变量名指向一个具体的值引用类型:变量名指向数据对象的内存地址2.在内存构造方面:值类型:变量声明后,Java会立即为其分配内存空间引用类型:以特殊方式指向对象实体(类似于C指针),当变量声明时不分配内存该类型变量是声明的,只是存储3.使用方面:值类型:使用时需要赋具体值,判断时使用“==”。引用类型:使用的时候可以赋null,判断的时候用equals。.自动转换的定义:在程序执行过程中“悄悄”进行的转换,不需要用户事先声明,一般是从位数少的类型转换到位数多的类型关系:从低到高的转换不同类型数据之间的优先级关系如下:低------------------------------------------->高字节、short、char->int->long->float->double转换规则:在运算中,先将不同类型的数据转换为同一类型,再进行运算执行的操作数1类型操作数2类型转换后的类型2.强制类型转换定义:强制类型转换必须在代码中声明,转换顺序不限。格式:在需要转换的数据前加上“()”,然后在括号中加上需要转换的数据类型。结果:精度可能丢失,或者更准确intx;doubley;x=(int)3.14+(int)5.20//精度损失y=(double)x+(double)8//精度提升output:x=8;y=16.0三、Java中的装箱和拆箱1、包装类Java是一种面向对象的语言,它宣称一切都是对象。因此,8种基本数据类型都有相应的类,即包装类2.什么是装箱和拆箱?类型转换为引用类型的过程拆箱:引用类型转换为值类型的过程自动装箱:intx=3;Integery=x;//int-->;Integer,Integery=x<==>Integery=Integer.valueOf(x)自动拆箱:Integerx=newInteger(5);inty=x;//Integer-->int,inty=x<==>inty=x.intValue()3.装箱和拆箱是如何实现的装箱过程是通过调用wrapper的valueOf方法实现的拆箱过程是通过调用wrapper的xxxValue方法实现的(xxx代表对应的基本数据类型)4.注意点:大量使用自动拆箱会降低性能,在重载的方法中会造成大量的内存消耗,可能会出现问题。Listlist=newArrayList<>();Integerx,y,z;x=1;y=2;z=4;list.add(x);list.add(y);list.add(z);list.remove(2);in上面代码中,ArrayList.remove方法有两个重载方法,所以list.remove(2)调用哪个方法,移除值为2的对象,或者移除对象索引为2,值为4的那个对象呢?在这种情况下,编译器不会自动解包盒子,所以调用是remove(intindex),索引为2,值为4的Integer对象将被移除。如果要调用remove(Objecto)方法,应该写成list.remove(y)3.缓存值问题案例分析:Integeri1=100;Integeri2=100;Integeri3=200;Integeri4=200;System.out.println(i1==i2);系统输出。println(i3==i4);Output:truefalse观察源码:Integer.valueOfmethodpublicstaticIntegervalueOf(inti){if(i>=IntegerCache.low&&i<=IntegerCache.high)returnIntegerCache.cache[i+(-IntegerCache.low)];returnnewInteger(i);}IntegerCache类privatestaticclassIntegerCache{staticfinalintlow=-128;staticfinalinthigh;staticfinalIntegercache[];static{//highvaluemaybeconfiguredbypropertyinth=127;StringintegerCacheHighPropValue=sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if(integerCacheHighPropValue!=null){try{inti=parseInt(integerCacheHighPropValue);i=Math.max(i,127);//MaximumarraysizeisInteger.MAX_VALUEh=Math.min(i,Integer.MAX_VALUE-(-low)-1);}catch(NumberFormatExceptionnfe){//如果属性不能解析成int,则忽略。}}hhigh=h;cache=newInteger[(high-低)+1];intj=low;for(intk=0;k=127;}privateIntegerCache(){}}从源码可以看出,通过valueOf方法创建Integer对象时,如果值在[-128,127]之间,会返回IntegerCache.cache中已有对象的引用;否则新建一个Integer对象Byte、Short、Integer、Long四个包装类默认创建对应类型缓存数据,值为[-128,127],但超出此范围仍会创建新对象角色默认会创建[0,127]响应类型的缓存数据。这两种浮点类型都没有实现常量池技术。一定范围内的整数值的个数是有限制的,但是浮点数不是包装类常量池常量。PoolscopeByteexists[-128,127]Shortexists[-128,127]Integerexists[-128,127]Longexists[-128,127]Characterexists[0,127]Float不存在NoneDouble不存在None注意:当“=”运算符If两个操作数都是wrapper类型的引用,比较它们是否指向同一个对象,如果其中一个操作数是表达式(即包含算术运算),比较的是一个值(即会触发automaticteardown)装箱过程)对于wrapper类型,equals方法不进行类型转换算术运算,触发装箱拆箱过程