当前位置: 首页 > 后端技术 > Java

第二天就辞职了,因为我改int为Integer

时间:2023-04-02 09:51:30 Java

int类型改成Integer类型,因为牵扯到钱,公司上线后损失惨重,程序员被辞退。信不信由你,请继续阅读。先看一段代码:publicstaticvoidmain(String[]args){Integera=Integer.valueOf(100);整数b=100;整数c=Integer.valueOf(129);整数d=129;System.out.println("a==b:"+(a==b));System.out.println("c==d:"+(c==d));}猜猜它的运行结果是什么?运行程序后,我们发现不对劲,得到了意想不到的运行结果,如下图所示。看到这个运行结果,肯定有人会问,为什么会这样?出现这个结果的原因是因为Integer使用的Flyweight模式。看Integer的源码,publicfinalclassIntegerextendsNumberimplementsComparable{...publicstaticIntegervalueOf(inti){if(i>=IntegerCache.low&&i<=IntegerCache.high)returnIntegerCache.cache[i+(-IntegerCache.low)];返回新整数(i);}...}继续进入IntegerCache的源码查看low和high的值:privatestaticclassIntegerCache{//Minimumstaticfinalintlow=-128;//最大值,支持自定义staticfinalinthigh;//缓存数组staticfinalIntegercache[];static{//最大值可以通过属性配置改变inth=127;StringintegerCacheHighPropValue=sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");//如果设置了相应的属性,则使用值if(integerCacheHighPropValue!=null){try{inti=parseInt(integerCacheHighPropValue);i=Math.max(i,127);//最大数组大小为Integer.MAX_VALUEh=Math.min(i,Integer.MAX_VALUE-(-low)-1);}catch(NumberFormatExceptionnfe){//如果无法将属性解析为int,则忽略它。}}高=h;cache=newInteger[(high-low)+1];intj=低;//实例化低-高范围内的所有值并将它们作为缓存存储在数组中usefor(intk=0;k=127;}privateIntegerCache(){}}由上可知,Integer源码中的valueOf()方法做了条件判断,如果目标值为-128-127,则直接从缓存中取值,否则新建object,其实Integer在第一次使用的时候,会初始化缓存,其中最小范围是-128,最大值默认是127。然后所有的数据从low到high会被初始化,存放在数据。默认情况下,从-128到127共256个数字会被循环实例化并存储在缓存数组中。准确的说,数组中应该存放这256个对象在内存中的地址。这里又有人会问了,为什么默认是-128-127,为什么不是-200-200或者其他值呢?那么JDK为什么要这样做呢?JavaAPI中是这样解释的:返回一个代表指定int值的Integer实例。如果不需要新的Integer实例,通常应优先使用此方法而不是构造函数Integer(int),因为此方法可能通过缓存频繁请求的值来产生明显更好的空间和时间性能。此方法将始终缓存-128到127(含)范围内的值,并可能缓存此范围之外的其他值Internal是最常用的。为了减少频繁创建对象带来的内存消耗,这里其实采用享元模式来提高空间和时间性能。JDK添加的默认范围不是不可变的。我们可以在使用前通过设置-Djava.lang.Integer.IntegerCache.high=xxx或者设置-XX:AutoBoxCacheMax=xxx来修改缓存范围,如下图所示:后来,我找到了另一种似是而非的解释:其实,当这个特性在Java5中首次引入,范围固定在-127到+127。后来在Java6中,范围的最大值被映射到java.lang.Integer.IntegerCache.high,这是一个允许我们设置高位位数的VM参数。它根据我们的应用程序用例灵活地调整性能。应该选择-127到127这个数字范围的原因是什么?这被认为是广泛使用的整数范围。在程序中首次使用Integer必须花费额外的时间来缓存实例。JavaLanguageSpecification的原文解释如下:理想情况下,装箱一个给定的原始值p,总是会产生一个相同的引用。实际上,使用现有的实现技术这可能不可行。上述规则是一种务实的妥协。上面的最后一条要求始终将某些公共值装箱到无法区分的对象中。实现可以懒惰地或急切地缓存这些。对于其他值,此公式不允许对程序员部分的盒装值的身份进行任何假设。这将允许(但不要求)共享部分或全部这些参考资料。这确保在大多数常见情况下,行为将是所需的行为,而不会造成不应有的性能损失,尤其是在小型设备上。例如,内存限制较少的实现可能会缓存所有char和short值,以及在-32K到+32K范围内的int和long值。2关于整数和int的比较\1)由整数变化实际上是对一个互联网ger对象引用,所以new生成的两个Integer变量永远不相等(因为new生成两个内存地址不同的对象)Integeri=newInteger(100);Integerj=newInteger(100);System.out.print(i==j);//false\2)当一个Integer变量与一个int变量进行比较时,只要两个变量的值相等,则结果为true(因为包装类Integer和基本数据类型int是比较,java会自动解压成int,然后比较,实际上就变成了两个int变量的比较)Integeri=newInteger(100);intj=100;System.out.print(i==j);//true\3)将非new生成的Integer变量与newInteger()生成的变量进行比较时,结果为false。(因为①当变量值在-128-127之间时,非new生成的Integer变量指向java常量池中的对象,newInteger()生成的变量指向堆中新创建的对象,两者在内存中的地址不同;②当变量值在-128-127之间时,非new生成一个Integer变量时,javaAPI最终会根据newInteger(i)进行处理(参考下文第4条),最后两个Integer的地址也不一样)Integeri=newInteger(100);Integerj=100;System.out.print(i==j);//false\4)对于两个非新生成的Integer对象,比较时,如果两个变量的值在-128到127范围内,则比较结果为真,如果两个变量的值变量不在这个范围内,比较结果为false3扩展知识在JDK中,此类应用比Int多,下面的wrapper类型也应用Flyweight模式,缓存值,只是缓存范围不同,如下图下表:Basictypesizeminimumvaluemaximumwrappertypecacherangesupportscustomboolean---Bloolean--char6bitUnicode0Unicode2(16)-1Character0~127Nobyte8bit-128+127Byte-128~127Noshort16bit-2(15)2(15)-1Short-128~127无int32bit-2(31)2(31)-1Integer-128~127支持long64bit-2(63)2(63)-1Long-128~127无float32bitIEEE754IEEE754Float-double64bitIEEE754IEEE754Double-void---Void--你觉得这个锅值不值?4使用享元模式实现数据库连接池再比如我们经常使用的数据库连接池,因为使用Connection对象时主要的性能消耗是在建立和关闭连接的时候。为了提高Connection对象在调用时的性能,在调用前先创建Connection对象并缓存,使用时直接从缓存中取值,用完后再放回去,达到目的的资源再利用。代码如下。公共类ConnectionPool{privateVector池;私有字符串url="jdbc:mysql://localhost:3306/test";私人字符串用户名=“根”;私人字符串密码=“root”;privateStringdriverClassName="com.mysql.jdbc.Driver";privateintpoolSize=100;publicConnectionPool(){pool=newVector(poolSize);试试{Class.forName(driverClassName);for(inti=0;i0){Connectionconn=pool.get(0);pool.remove(conn);返回康恩;}返回空值;}publicsynchronizedvoidrelease(Connectionconn){pool.add(conn);}}这类连接池在开源框架中被广泛使用,可以有效提升底层运行性能

最新推荐
猜你喜欢