疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java基础之包装类的自动装箱和拆箱详解


 

   

  定义

  在java中,数据类型可以分为两大类,即基本数据类型和引用数据类型,基本数据类型的数据不是对象,所以对于要将数据类型作为对象来使用的情况,java提供了相对应的包装类。(关于包装类的详细介绍请参看博客Java基础之常用类详解)

  本篇博客主要讲述包装类的自动装箱和拆行机制。

  所谓装箱,就是把基本数据类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,如我们可以把int类型包装成Integer类型的对象,或者把double包装秤Double,等等。

  所谓拆箱,就是和装箱的方向相反,将Integer即Double这样的引用类型的对象重新简化成基本数据类型的数据。

  而java JDK引入的自动装箱和拆箱就是编译器来依据我们编写的代码,决定是否进行装箱和拆箱动作。即无需使用valueOf()和intValue()等方法。(如果这方面不熟悉请参看博客Java基础之常用类详解)

  关于自动装箱拆箱机制的注意事项

  这是本篇博客要讲述的重点

  先看一个小例子:

  public class WrapperText {

  public static void main(String[] args) {

  Integer a = 100;

  Integer b = 100;

  Integer c = 200;

  Integer d = 200;

  System.out.println(a == b);//1

  System.out.println(a == 100);//2

  System.out.println(c == d);//3

  System.out.println(c == 200);//4

  }

  }

  如果我们对于Java中自动装箱和拆箱操作了解不够深入的话,一定会这么想:自动装箱后,abcd都是Integer对象的不同引用,“==”操作符又是用来比较对象引用的,所以1和3都应输出false。而对于2和4,由于a和c都进行了自动拆箱,因此其比较是基本数据类型的比较。“==”操作符比较的使它们的值,所以2和4因该输出true。即最终结果输出:

  false

  true

  false

  true

  但是正确的结果却是:

  true

  true

  false

  true

  我们看到1的结果为true,3的结果为false,这是为什么呢。其实很简单,自动装箱过程其实是调用了valueOf()的方法,而valueOf()方法的源码为:

  public static Integer valueOf(int i) {

  assert IntegerCache.high >= 127;

  if (i >= IntegerCache.low && i <= IntegerCache.high)

  return IntegerCache.cache[i + (-IntegerCache.low)];

  return new Integer(i);

  }

  1

  private static class IntegerCache {

  static final int low = -128;

  static final int high;

  static final Integer cache[];

  static {

  // high value may be configured by property

  int h = 127;

  String integerCacheHighPropValue =

  sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

  if (integerCacheHighPropValue != null) {

  int i = parseInt(integerCacheHighPropValue);

  i = Math.max(i, 127);

  // Maximum array size is Integer.MAX_VALUE

  h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

  }

  high = h;

  cache = new Integer[(high - low) + 1];

  int j = low;

  for(int k = 0; k < cache.length; k++)

  cache[k] = new Integer(j++);

  }

  private IntegerCache() {}

  }

  通过阅读源代码,可以发现,java内部为了节省内存,IntegerCache类中有一个数组缓存了值从-128到127的Integer对象。当我们调用Integer.valueOf(int i)的时候,如果i的值时结余-128到127之间的,会直接从这个缓存中返回一个对象,否则就new一个新的Integer对象。因此,1为true,3为false。

  最后分享一道与之相关的很有意思的题目:

  请提供一个对i的声明,将下面的循环转变成为一个无限循环:

  while(j <= i && i <= j && i != j){

  }