开启掘金成长之旅!这是我参与掘金日新计划2月更文挑战的第2天,点击查看活动详情 Integer面试中我们经常被问到,另外工作中我们也经常遇到Integer的比较,所以今天来快速总结下这个知识点。 首先我们假设声明了两个局部变量:Integeri200;Integerj100;复制代码 事实上,Java最终的逻辑是不管你后边的数是多少,最终都会调Integer。valueOf(i);来将给定的数值,进行装箱操作,但是里边会判断,就是如果给定数值i是在127128之间的数值,那么将会从一个Integer类型的缓存数组中拿到指定位置(即index是给定数值的)对应的Integer对象,如果给定数值i不在127128范围内,那么将会在堆上开辟空间,new一个Integer对象出来 空口无凭,我们使用命令反汇编一下,看看到底是是不是会像上边说的那样;执行命令: JavappvctargettestclassescomxzlltestmianshiIntegerCacheTest。class 结果如下: 2。IntegerCache初始化源码valueOf简析 我们看下这个逻辑,Integer类源码如下:publicfinalclassIntegerextendsNumberimplementsComparableInteger{privatestaticclassIntegerCache{下界staticfinalintlow128;上界,可通过XX:AutoBoxCacheMaxsize来调整大小,但是不能超过Inter。MAX,并且小于127的话,就还是取127这个就是存储Integer对象的数组了staticfinalInteger〔〕staticInteger〔〕archivedCstatic{highvaluemaybeconfiguredbypropertyinth127;StringintegerCacheHighPropValueVM。getSavedProperty(java。lang。Integer。IntegerCache。high);一堆判断,判断是用你配的?还是默认的?,上限值if(integerCacheHighPropValue!null){try{intiparseInt(integerCacheHighPropValue);iMath。max(i,127);MaximumarraysizeisInteger。MAXVALUEhMath。min(i,Integer。MAXVALUE(low)1);}catch(NumberFormatExceptionnfe){Ifthepropertycannotbeparsedintoanint,ignoreit。}}LoadIntegerCache。archivedCachefromarchive,ifpossibleVM。initializeFromArchive(IntegerCache。class);intsize(highlow)1;Usethearchivedcacheifitexistsandislargeenough新建一个Integer数组,初始值为128,127,。。。,0,1,2,。。。,127if(archivedCachenullsizearchivedCache。length){Integer〔〕cnewInteger〔size〕;for(intk0;kc。k)c〔k〕newInteger(j);赋值给archivedCache变量archivedC}赋值给cache变量cachearchivedCrange〔128,127〕mustbeinterned(JLS75。1。7)assertIntegerCache。high127;}privateIntegerCache(){}}publicstaticIntegervalueOf(inti){if(iIntegerCache。lowiIntegerCache。high)returnIntegerCache。cache〔i(IntegerCache。low)〕;不newobject,而是直接从cache中读出object返回returnnewInteger(i);new一个Integer对象返回}}复制代码 上边代码比较简单,我们不过多展开了3。演示一下各种对比以及结果:publicstaticvoidmain(String〔〕args){inti1200;Integeri2200;System。out。println(i1i2:结果:(i1i2),int和new出来的Integer(因为200不在(127128)区间,所以会new对象)比较,i2会自动拆箱所以会变成两个int的比较);Integeri3200;编译后,此处变为Integeri3Integer。valueOf(200);也就是说不会从IntegerCache中获取,而是new了一个对象Integeri4200;System。out。println(i3i4:结果:(i3i4),由于200不在缓存127128之间,所以此处是两个对象的比较,i3内存地址:System。identityHashCode(i3),i4内存地址:System。identityHashCode(i4));Integeri15newInteger(100);Integeri16newInteger(100);System。out。println(i15i16:结果:(i15i16),i15和i16是new的两个对象,i15内存地址:System。identityHashCode(i15),i16内存地址:System。identityHashCode(i16));Integeri17100;System。out。println(i15i17:结果:(i15i17),由于i15是new的对象,i17是从Integer缓存数组中拿的对象,两个都是对象,i15内存地址:System。identityHashCode(i15),i17内存地址:System。identityHashCode(i17));Integeri18100;System。out。println(i17i18:结果:(i17i18),由于100在缓存127128之间,所以此处是两个相同对象的比较(因为都是从数组中拿的同一个index位置的Integer对象),i17内存地址:System。identityHashCode(i17),i18内存地址:System。identityHashCode(i18));inti100100;System。out。println(i5i100:结果:(i15i100),由于i100是基础类型,和从Integer缓存中拿出来的i17(Integer对象比较)比较,i17会自动拆箱,结果自然是true);}复制代码 输出:i1i2:结果:true,int和new出来的Integer(因为200不在(127128)区间,所以会new对象)比较,i2会自动拆箱所以会变成两个int的比较i3i4:结果:false,由于200不在缓存127128之间,所以此处是两个对象的比较,i3内存地址:706197430,i4内存地址:1325808650i15i16:结果:false,i15和i16是new的两个对象,i15内存地址:510464020,i16内存地址:1987083830i15i17:结果:false,由于i15是new的对象,i17是从Integer缓存数组中拿的对象,两个都是对象,i15内存地址:510464020,i17内存地址:1632492873i17i18:结果:true,由于100在缓存127128之间,所以此处是两个相同对象的比较(因为都是从数组中拿的同一个index位置的Integer对象),i17内存地址:1632492873,i18内存地址:1632492873i5i100:结果:true,由于i100是基础类型,和从Integer缓存中拿出来的i17(Integer对象比较)比较,i17会自动拆箱,结果自然是true复制代码 (idea运行)附图如下: 3。1做个小总结无论如何,I与newInteger(xxx)不会相等。不会经历拆箱过程两个都是非new出来的Integer对象(即Integerixxx),如果xxx在128到127之间,则是true,否则为false两个都是new出来的,都为falseint和Integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比4。事实上,不仅Integer这么做,其他也有类似做法,如下有ByteCache用于缓存Byte对象有ShortCache用于缓存Short对象有LongCache用于缓存Long对象有CharacterCache用于缓存Character对象 Byte,Short,Long有固定范围:128到127。对于Character,范围是0到127。除了Integer可以通过参数改变范围外,其它的都不行。 可以看出来jdk的大佬们是多么的追求极致! 一天一小步,一年一大步! ps:今晚是通宵上线的一晚,请bug远离我