黑马程序员技术交流社区

标题: 关于基本数据类型自动装箱的问题 [打印本页]

作者: 克零岚    时间: 2013-3-3 15:36
标题: 关于基本数据类型自动装箱的问题
  1. public class test {
  2. public static void main(String[] args) {
  3.   Integer i1=3;
  4.   Integer i2=3;
  5.   System.out.println(i1==i2);//结果显示为true
  6.   Integer i3=145;
  7.   Integer i4=145;
  8.   System.out.println(i3==i4);//结果却显示为false,查了查资料,
  9.   //人家说只能接受-128--127之间的数,int类型不是4个字节嘛,取值范围在(-2147483648~2147483647)
  10.   //完全有能力包括145这个数字啊,自动装箱过程中在缓存中发生了什么呢?
  11.   //那么对于其它基本数据类型的装箱过程中也存在类似的限制吗?求解
  12. }
  13. }

  14. <p> </p>
复制代码

作者: 黑马斯巴达    时间: 2013-3-3 15:56
  自动装箱时,它的范围是一个字节,所以对于值从-128-127之间的数,被装箱后,会被放在内存中进行重用,如果超出了这个值的范围就不会被重用的,就像new出来的都是一个新的对象,结果就是false。
他的范围并不是int的范围……
作者: 克零岚    时间: 2013-3-3 16:03
追问:对于浮点数float  a =1与float    a  =1.0有什么区别呢?
  1. public static void main(String args[]) {
  2.                      try {
  3.                      double a =1.0;
  4.                      float b= (float) a;
  5.        float c = 1.0;  //这行编译时就报错
  6.       float   a=1;            
  7.        System.out.println(b);
  8.                      }
  9.                      catch(Exception e) {}
  10.                    }
复制代码
转换成float类型时它们发生了什么呢?


作者: 克零岚    时间: 2013-3-3 16:06
谢军 发表于 2013-3-3 15:56
自动装箱时,它的范围是一个字节,所以对于值从-128-127之间的数,被装箱后,会被放在内存中进行重用,如 ...

那其它基本数据类型的包装类呢,也有这方面的限制吗
作者: 夏振博    时间: 2013-3-3 16:11
编译器先把1.0转换成int类型 就是1 等赋值时发现赋值的时候变量类型是float类型,编译器就报错,至于为什么这样就报错?这是编译器的问题了,java是人写的,规定是人规定的,不要纠结这些固定格式的问题
作者: 黑马斯巴达    时间: 2013-3-3 16:16
本帖最后由 谢军 于 2013-3-3 16:18 编辑
克零岚 发表于 2013-3-3 16:06
那其它基本数据类型的包装类呢,也有这方面的限制吗

Java认为 -128~ 127 (byte)的范围是 最常用的,所以 自动装箱的时候(int -> Integer)
的时候会将该范围的整数缓存起来,当再次使用的时候不会生成新的值而是用原来的。也就是说只在这个范围的才会自动装箱,其他的也一样要在这这个范围
作者: 克零岚    时间: 2013-3-3 16:19
谢军 发表于 2013-3-3 16:16
Java认为 -128~ 127 (byte)的范围是 最常用的,所以 自动装箱的时候(int -> Integer)
的时候会将该范围 ...

哥,小弟受用了,真棒!
作者: 黑马斯巴达    时间: 2013-3-3 16:21
克零岚 发表于 2013-3-3 16:19
哥,小弟受用了,真棒!

慢慢来。认真学。学完了都会很棒的{:3_57:}
作者: 克零岚    时间: 2013-3-3 16:26
在网上看到的,希望对在这方面有欠缺的同学有帮助
关于java基本数据类型的包装类的自动装箱池的大小

     一直以为Integer的自动装箱池的大小是-128~127,今天看了jdk1.6的源代码,发现其实并不一定的。大家都知道java8种基本类型,它们都有自己的包装类。而Byte,Character,Short,Integer,Long都有一个自动装箱池,我一开始以为除了Character的自动装箱池的大小为0~127以外,其他都是-128~127。但是我在看jdk源代码的时候发现Integer的自动装箱池的实现跟其他几个包装类并不一样,我们先来看看Integer类好Short两个包装类的实现。
  1. Integer类的自动装箱池的实现:

  2. private static class IntegerCache {
  3.         static final int high;
  4.         static final Integer cache[];

  5.         static {
  6.             final int low = -128;

  7.             // high value may be configured by property
  8.             int h = 127;
  9.             if (integerCacheHighPropValue != null) {
  10.                 // Use Long.decode here to avoid invoking methods that
  11.                 // require Integer's autoboxing cache to be initialized
  12.                 int i = Long.decode(integerCacheHighPropValue).intValue();
  13.                 i = Math.max(i, 127);
  14.                 // Maximum array size is Integer.MAX_VALUE
  15.                 h = Math.min(i, Integer.MAX_VALUE - -low);
  16.             }
  17.             high = h;

  18.             cache = new Integer[(high - low) + 1];
  19.             int j = low;
  20.             for(int k = 0; k < cache.length; k++)
  21.                 cache[k] = new Integer(j++);
  22.         }

  23.         private IntegerCache() {}
  24.     }

  25. <p>Short和其他包装类(Character除外,不过原理一样,只是范围不一样)的自动装箱池的实现:</p>
  26. <div class="cnblogs_code"><pre><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> ShortCache {
  27.     </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> ShortCache(){}

  28.     </span><span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">final</span> Short cache[] = <span style="color: rgb(0, 0, 255);">new</span> Short[-(-128) + 127 + 1<span style="color: rgb(0, 0, 0);">];

  29.     </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> {
  30.         </span><span style="color: rgb(0, 0, 255);">for</span>(<span style="color: rgb(0, 0, 255);">int</span> i = 0; i < cache.length; i++<span style="color: rgb(0, 0, 0);">)
  31.         cache[i] </span>= <span style="color: rgb(0, 0, 255);">new</span> Short((<span style="color: rgb(0, 0, 255);">short</span>)(i - 128<span style="color: rgb(0, 0, 0);">));
  32.     }
  33.     }</span></pre></div>
  34. <p>经过比较我们发现,Integer的自动装箱池的最大值并不是一直是127的,当integerCacheHighPropValue不为空的时候,最大值是由integerCacheHighPropValue决定的。我们来看看integerCacheHighPropValue的是在哪儿被赋值的:</p>
  35. <div class="cnblogs_code"><pre><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> String integerCacheHighPropValue;

  36.     </span><span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> getAndRemoveCacheProperties() {
  37.         </span><span style="color: rgb(0, 0, 255);">if</span> (!<span style="color: rgb(0, 0, 0);">sun.misc.VM.isBooted()) {
  38.             Properties props </span>=<span style="color: rgb(0, 0, 0);"> System.getProperties();
  39.             integerCacheHighPropValue </span>=<span style="color: rgb(0, 0, 0);">
  40.                 (String)props.remove(</span>"java.lang.Integer.IntegerCache.high"<span style="color: rgb(0, 0, 0);">);
  41.             </span><span style="color: rgb(0, 0, 255);">if</span> (integerCacheHighPropValue != <span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)
  42.                 System.setProperties(props);  </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> remove from system props</span>
  43. <span style="color: rgb(0, 0, 0);">        }
  44.     }</span></pre></div>
  45. <p>这段代码告诉我们,integerCacheHighPropValue是通过读取系统配置获得的,也就是说Integer的自动装箱池的大小是可以配置的。我们来看看</p>
  46. <p>getAndRemoveCacheProperties方法的注释就一目了然了。<img alt="" src="http://pic002.cnblogs.com/images/2012/160039/2012071512430459.png"></p>
  47. <p>我们可以在虚拟机参数里面配置Integer的自动装箱池的大小。我们来验证一下。</p>
  48. <p>默认配置时,<img alt="" src="http://images.cnblogs.com/cnblogs_com/itnote/396086/r_QQ%e6%88%aa%e5%9b%be20120715124904.png" width="539" height="114"></p>
  49. <p><img alt="" src="http://images.cnblogs.com/cnblogs_com/itnote/396086/r_QQ%e6%88%aa%e5%9b%be20120715125351.png" width="338" height="333"> </p>
  50. <p> 结果:<img alt="" src="http://images.cnblogs.com/cnblogs_com/itnote/396086/r_QQ%e6%88%aa%e5%9b%be20120715125551.png" width="205" height="87"></p>
  51. <p>修改虚拟机参数:<img alt="" src="http://images.cnblogs.com/cnblogs_com/itnote/396086/r_QQ%e6%88%aa%e5%9b%be20120715125722.png" width="436" height="84"></p>
  52. <p>结果:<img alt="" src="http://images.cnblogs.com/cnblogs_com/itnote/396086/r_QQ%e6%88%aa%e5%9b%be20120715125852.png" width="184" height="88"></p>
  53. <p>我们修改Integer的自动装箱池的大小为256。所以第二个输出的结果为true。由于第四个输出仍为false,所以我们还可以推断:修改虚拟机的AutoBoxCacheMax的大小只会影响Integer,而不会影响其他包装类。为什么其他包装类不跟Integer一样设计成可配置的呢?这就不得而知了。</p>
复制代码

作者: 克零岚    时间: 2013-3-3 16:26
谢军 发表于 2013-3-3 16:21
慢慢来。认真学。学完了都会很棒的

:handshake恩呢
作者: 克零岚    时间: 2013-3-3 16:33
在网上看到的,希望对在这方面有欠缺的同学有帮助
关于java基本数据类型的包装类的自动装箱池的大小,链接在此
http://www.16kan.com/post/207405.html

作者: 邹学良    时间: 2013-3-3 16:56
克零岚 发表于 2013-3-3 16:03
追问:对于浮点数float  a =1与float    a  =1.0有什么区别呢?转换成float类型时它们发生了什么呢?

...

从宽数据类型转换成窄数据类型时,会出现载断现象。而强制类型转换比任何操作符的优先等级都要高,所以才会导致编译时报错




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2