int

  1. Java基本数据类型
  2. 直接存储为数据值,保存在栈中
  3. 无需初始化,默认值为0

Integer

  1. 包装类,基本数据类型int的包装类
  2. 对象,存储为对象在内存的引用,对象的引用保存在栈中,数据存储在堆内存中
  3. 对象,必须初始化才可以使用,默认值为null

重点知识点

基本数据类型

分为boolean、byte、int、char、long、short、double、float;

引用数据类型

分为数组、类、接口、数组、枚举、标注;

Java原始类型的封装类

为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每 一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

自动装箱和自动拆箱

自动装箱:将基本数据类型重新转化为对象
自动拆箱:将对象重新转化为基本数据类型

相同值下的 int 和 Integer 的比较结果

两个通过new生成的变量,结果为false。

  1. Integer i1 = new Integer(10);
  2. Integer i2 = new Integer(10);
  3. System.out.print(i1 == i2); //false

int 和 Integer 的值比较,若两者的值相等,则为true。(注意:在比较时,Integer会自动拆箱为int类型,然后再做比较,实际上就变为两个int变量的比较)

  1. Integer i1 = new Integer(10);
  2. int i2 = 10
  3. System.out.print(i1 == i2); //true

new 生成的Integer变量 和 非new 生成的Integer变量比较,结果为false。(注意:new 生成的Integer变量的值在堆空间中,非new 生成的Integer变量的值在在常量池中。非new生成的Integer变量,会先判断常量池中是否有该对象,若有则共享,若无则在常量池中放入该对象;这也叫享元模式)

  1. Integer i1 = new Integer(10);
  2. Integer i2 = 10;
  3. System.out.print(i1 == i2); //false

对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。

  1. Integer i1 = 10;
  2. Integer i2 = 10;
  3. System.out.print(i1 == i2); //true
  4. Integer j1 = 128;
  5. Integer j2 = 128;
  6. System.out.print(j1 == j2); //false
  7. 复制代码

当值在 -128 ~ 127之间时,java会进行自动装箱,然后会对值进行缓存,如果下次再有相同的值,会直接在缓存中取出使用。缓存是通过Integer的内部类IntegerCache来完成的。当值超出此范围,会在堆中new出一个对象来存储。

源码分析

Integer 类中有2种构造方法,如下:
image.png
2个构造方法都比较清晰,将输入的值初始化赋值

  1. /**
  2. * Constructs a newly allocated {@code Integer} object that
  3. * represents the specified {@code int} value.
  4. *
  5. * @param value the value to be represented by the
  6. * {@code Integer} object.
  7. */
  8. public Integer(int value) {
  9. this.value = value;
  10. }
  11. /**
  12. * Constructs a newly allocated {@code Integer} object that
  13. * represents the {@code int} value indicated by the
  14. * {@code String} parameter. The string is converted to an
  15. * {@code int} value in exactly the manner used by the
  16. * {@code parseInt} method for radix 10.
  17. *
  18. * @param s the {@code String} to be converted to an
  19. * {@code Integer}.
  20. * @exception NumberFormatException if the {@code String} does not
  21. * contain a parsable integer.
  22. * @see java.lang.Integer#parseInt(java.lang.String, int)
  23. */
  24. public Integer(String s) throws NumberFormatException {
  25. this.value = parseInt(s, 10);
  26. }

JDK1.5之后,java提供了自动装箱和自动拆箱的功能。自动装箱也就是调用了Integer类的一个静态方法valueOf方法,源码如下:

  1. /**
  2. * Returns an {@code Integer} instance representing the specified
  3. * {@code int} value. If a new {@code Integer} instance is not
  4. * required, this method should generally be used in preference to
  5. * the constructor {@link #Integer(int)}, as this method is likely
  6. * to yield significantly better space and time performance by
  7. * caching frequently requested values.
  8. *
  9. * This method will always cache values in the range -128 to 127,
  10. * inclusive, and may cache other values outside of this range.
  11. *
  12. * @param i an {@code int} value.
  13. * @return an {@code Integer} instance representing {@code i}.
  14. * @since 1.5
  15. */
  16. public static Integer valueOf(int i) {
  17. if (i >= IntegerCache.low && i <= IntegerCache.high)
  18. return IntegerCache.cache[i + (-IntegerCache.low)];
  19. return new Integer(i);
  20. }

其中可以看到,针对参数i进行了IntegerCache.low和IntegerCache.high的比较,如果在此范围内,则直接返回cache数组中的内容,如果不在此范围内,则new一个新的Integer对象返回。

我们继续看IntegerCache类具体做了哪些内容。

  1. private static class IntegerCache {
  2. static final int low = -128;
  3. static final int high;
  4. static final Integer cache[];
  5. static {
  6. // high value may be configured by property
  7. int h = 127;
  8. String integerCacheHighPropValue =
  9. sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
  10. if (integerCacheHighPropValue != null) {
  11. try {
  12. int i = parseInt(integerCacheHighPropValue);
  13. i = Math.max(i, 127);
  14. // Maximum array size is Integer.MAX_VALUE
  15. h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
  16. } catch( NumberFormatException nfe) {
  17. // If the property cannot be parsed into an int, ignore it.
  18. }
  19. }
  20. high = h;
  21. cache = new Integer[(high - low) + 1];
  22. int j = low;
  23. for(int k = 0; k < cache.length; k++)
  24. cache[k] = new Integer(j++);
  25. // range [-128, 127] must be interned (JLS7 5.1.7)
  26. assert IntegerCache.high >= 127;
  27. }
  28. private IntegerCache() {}
  29. }

在上面源码可以清晰的看到,IntegerCache中有3个常量,low为最小范围,high为最大范围,cache数组缓存了基本数据内容,其次,IntegerCache中还有一个静态代码块,用来初始化以上数据内容。
如果VM环境设置了java.lang.Integer.IntegerCache.high变量,则high=设置的值如果小于127则取127,如果大于Integer.MAX_VALUE-128-1,则取Integer.MAX_VALUE-128-1。
最后会根据大小初始化cache数据内容,这些数据都是static,会保存在栈内存中。

  • 缓存支持自动装箱的对象标识语义 -128 <= i <= 127
  • 缓存在第一次使用时初始化。 缓存的大小可以由-XX:AutoBoxCacheMax = 选项控制
  • 在VM初始化期间,java.lang.Integer.IntegerCache.high属性可以设置并保存在私有系统属性