菜鸟学习javaweb(一)--自动拆装箱

来源:互联网 发布:洪玄公捏脸数据 编辑:程序博客网 时间:2024/06/01 09:32

       在学习C#的时候,我们都知道有装箱和拆箱这么一个概念.装箱(Boxing)是隐式的将一个值类型转换为一个object类型.拆箱就是将一个已装箱的object类型对象转换成一个值类型.装箱和拆箱的过程都反复在堆(Heep)和堆栈(Stack)中进行,占用大量的内存.在写程序中,要求资源合理的利用,才能提高程序的运行速度,所以在写程序的时候应该避免无意义的装箱和拆箱工作.


       在文章开头提到装箱和拆箱,接着来主要是和大家分享一下自动拆装箱.自动拆装箱是JDK5.0的新特性之一.这一特性可以使基本类型,与之对应的包装器类型之间直接转换,例如int的包装器类型是Integer!在JDK5.0之后,你甚至可以把int当作成Integer来使用,把Integer当成int来使用。


.概述

Java允许把基本类型与其对应的包装器类型之间自动相互转换。

  • 自动装箱:Integer i=(int)100,int类型的直接赋值给Integer类型;
  • 自动拆箱:int a=new Integer(100),Integer类型直接赋值给int类型

 

 

.原理

自动拆装箱是由编译器完成的!我们写的代码,再由编译器“二次加工”,然后再编译成.class文件!

  • int a = new Integer(100); 编译器加工为:int a = new Integer(100).intValue();
  • Integer b = a;编译加工后为:  Integer b = Integer.valueOf(a);

.误区

 先来看下面一段代码:

int[] intArr = {1,2,3};Integer[] integerArr = intArr;

编译是无法通过,而且运行的时候会报这么一个错误


       那么为什么编译的时候无法通过呢?

       原因是int[]是引用类型,而不是基本类型。而自动拆装箱只是在基本类型与其对应的包装器类型之间进行转换!也就是说,int[]Integer[]是两种不同的引用类型。

 

.一个小的题目

题目:

Integer i1 = 100;Integer i2 = 100;Integer i3 = 200;Integer i4 = 200;System.out.println(i1 == i2);System.out.println(i3 == i4);

       如果这道题给你做,你的答案会是什么?是两个true,还是两个false.两个true或者两个两个false都是错的.答案是truefalse.这个疑团要从编译器加工后的代码开始,我们先来看编译器加工过后的代码:

Integer i1 = Integer.valueOf(100);Integer i2 = Integer.valueOf(100);Integer i3 = Integer.valueOf(200);Integer i4 = Integer.valueOf(200);System.out.println(i1 == i2);System.out.println(i3 == i4);


除了看编译器加工后的代码,我们再看看Integer的一个方法:

 public static Integer valueOf(int i) {final int offset = 128;if (i >= -128 && i <= 127) { // must cache     return IntegerCache.cache[i + offset];}        return new Integer(i);    }

       结合以上两个片段你应该可以看到,疑团在Integer.valueOf()方法身上。传递给这个方法100时,它返回的Integer对象是同一个对象,而传递给这个方法200时,返回的却是不同的对象。这是我们需要打开Integer的源码(这里就不粘贴Integer的源代码了),查看它的valueOf()方法内容。


       Integer类的内部缓存了-128~127之间的256个Integer对象,如果valueOf()方法需要把这个范围之内的整数转换成Integer对象时,valueOf()方法不会去new对象,而是从缓存中直接获取,这就会导致valueOf(100)两次,都是从缓存中获取的同一个Integer对象!如果valueOf()方法收到的参数不在缓存范围之内,那么valueOf()方法会new一个新对象!这就是为什么Integer.valueOf(200)两次返回的对象不同的原因了。其中Integer的取值范围是在学习VB的时候学习的.

 

       Jdk5.0的自动拆装箱是借鉴了C#中的拆装箱,在使用拆装箱的时候,同时要考虑值类型的取值范围.




0 0
原创粉丝点击