int和Integer有什么区别?

无意中又看到了这个问题,今天总结一下

    一、  int就是我们常说的java八大(primitive types : blooean、 byte 、 short 、 char 、int 、 float 、 double 、 long)原始数据类型之一。java虽然号称一切皆对象但是基本数据类型是例外。

【八种基本数据类型的包装类】

byte ——Byte

short ——Short

int ——Integer

long-----Long

float-----Float

double----Double 

char----Character

boolean---Boolean

4.2.1. Integral Types and Values

The values of the integral types are integers in the following ranges:

  • For byte, from -128 to 127, inclusive
  • For short, from -32768 to 32767, inclusive
  • For int, from -2147483648 to 2147483647, inclusive
  • For long, from -9223372036854775808 to 9223372036854775807, inclusive
  • For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535

 

Integer是int对应的包装类,在 Java 5 中,引入了自动装箱和自动拆箱功能(boxing/unboxing),Java 可以根据上下文,自动进行转换,极大地简化了相关编程。

关于 Integer 的值缓存,这涉及 Java 5 中另一个改进。构建 Integer 对象的传统方式是直接调用构造器,直接 new 一个对象。但是根据实践,我们发现大部分数据操作都是集中在有限的、较小的数值范围,因而,在 Java 5 中新增了静态工厂方法 valueOf,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照 Javadoc,这个值默认缓存是 -128 到 127 之间。

 

 

二、那么为什么会有这个设计呢?

      原始数据类型和 Java 泛型并不能配合使用,也就是Primitive Types 和Generic 不能混用,于是JAVA就设计了这个auto-boxing/unboxing机制,实际上就是primitive value 与 object之间的隐式转换机制,否则要是没有这个机制,开发者就必须每次手动显示转换,那多麻烦是不是?但是primitive value 与 object各自有各自的优势,primitive value在内存中存的是值,所以找到primitive value的内存位置,就可以获得值;不像object存的是reference,找到object的内存位置,还要根据reference找下一个内存空间,要产生更多的IO,所以计算性能比primitive value差,但是object具备generic的能力,更抽象,解决业务问题编程效率高。于是JAVA设计者的初衷估计是这样的:如果开发者要做计算,就应该使用primitive value如果开发者要处理业务问题,就应该使用object,采用Generic机制;反正JAVA有auto-boxing/unboxing机制,对开发者来讲也不需要注意什么。然后为了弥补object计算能力的不足,还设计了static valueOf()方法提供缓存机制,算是一个弥补。

 

 

三、再说一下关于缓存的问题

关于 Integer 的值缓存,这涉及 Java 5 中另一个改进。构建 Integer 对象的传统方式是直接调用构造器,直接 new 一个对象。但是根据实践,我们发现大部分数据操作都是集中在有限的、较小的数值范围,因而,在 Java 5 中新增了静态工厂方法 valueOf,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照 Javadoc,这个值默认缓存是 -128 到 127 之间。

源码:[

This method will always cache values in the range -128 to 127,

* inclusive, and may cache other values outside of this range.

 

public static Integer valueOf(int i) {

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

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

return new Integer(i);

}

]

面试题:

Integer i1=123;

Integer i2=123;

System.out.println(i1==i2);//true

Integer i3=128;

Integer i4=128;

System.out.println(i3==i4);//false

解析:“==”对于引用类型比较的是对象地址是否相同,

JVM会自动维护八种基本类型的常量池,int常量池中初始化-128~127的范围,所以当为Integer i=127时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时,128不在常量池范围内,所以在自动装箱过程中需new 128,所以地址不一样。

Integer i1=new Integer(123);

Integer i2=new Integer(123);

System.out.println(123==i1);//true

System.out.println(i1==i2);//false

 

Integer i3=new Integer(128);

Integer i4=new Integer(128);

System.out.println(i3==i4);//false

System.out.println(128==i3);//true

解析:以上结果说明:

a.当数值范围为-128~127时:如果两个new出来Integer对象,即使值相同,通过“==”比较结果为false,但两个对象直接赋值,则通过“==”比较结果为“true,这一点与String非常相似。

b.当数值不在-128~127时,无论通过哪种方式,即使两个对象的值相等,通过“==”比较,其结果为false;

c.当一个Integer对象直接与一个int基本数据类型通过“==”比较,其结果与第一点相同;

d.Integer对象的hash值为数值本身;

 

源码:/** 

  1.    * Returns a hash code for this {@code Integer}. 
  2.    * 
  3.    * @return  a hash code value for this object, equal to the 
  4.    *          primitive {@code int} value represented by this 
  5.    *          {@code Integer} object. 
  6.    */  
  7.   public int hashCode() {  
  8.       return value;  
  9.   }  

Integer重写了hashCode方法,返回值是value,即Integer对象 的数值。

 

第二个问题,为什么Integer对象的范围是-128~127?

查看Integer类源码,发现里面有一个私有的静态内部类IntegerCache,而如果直接将一个基本数据类型的值赋给Integer对象,则会发生自动装箱,其原理就是通过调用Integer类的public static Integer valueOf(将int类型的值包装到一个对象中 ,其部分源码如下:

  1. /** 
  2.     * Cache to support the object identity semantics of autoboxing for values between 
  3.     * -128 and 127 (inclusive) as required by JLS. 
  4.     * 
  5.     * The cache is initialized on first usage.  The size of the cache 
  6.     * may be controlled by the -XX:AutoBoxCacheMax= option. 
  7.     * During VM initialization, java.lang.Integer.IntegerCache.high property 
  8.     * may be set and saved in the private system properties in the 
  9.     * sun.misc.VM class. 
  10.     */  
  11.   
  12.    private static class IntegerCache {  
  13.        static final int low = -128;  
  14.        static final int high;  
  15.        static final Integer cache[];  
  16.   
  17.        static {  
  18.            // high value may be configured by property  
  19.            int h = 127;  
  20.            String integerCacheHighPropValue =  
  21.                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");  
  22.            if (integerCacheHighPropValue != null) {  
  23.                int i = parseInt(integerCacheHighPropValue);  
  24.                i = Math.max(i, 127);  
  25.                // Maximum array size is Integer.MAX_VALUE  
  26.                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);  
  27.            }  
  28.            high = h;  
  29.   
  30.            cache = new Integer[(high - low) + 1];  
  31.            int j = low;  
  32.            for(int k = 0; k < cache.length; k++)  
  33.                cache[k] = new Integer(j++);  
  34.        }  
  35.   
  36.        private IntegerCache() {}  
  37.    }  
  38.   ..................  
  39.  ...................  
  40.  ...................  
  41.   
  42.      /** 
  43.     * Returns an {@code Integer} instance representing the specified 
  44.     * {@code int} value.  If a new {@code Integer} instance is not 
  45.     * required, this method should generally be used in preference to 
  46.     * the constructor {@link #Integer(int)}, as this method is likely 
  47.     * to yield significantly better space and time performance by 
  48.     * caching frequently requested values. 
  49.     * 
  50.     * This method will always cache values in the range -128 to 127, 
  51.     * inclusive, and may cache other values outside of this range. 
  52.     * 
  53.     * @param  i an {@code int} value. 
  54.     * @return an {@code Integer} instance representing {@code i}. 
  55.     * @since  1.5 
  56.     */  
  57.    public static Integer valueOf(int i) {  
  58.        assert IntegerCache.high >= 127;  
  59.        if (i >= IntegerCache.low && i <= IntegerCache.high)  
  60.            return IntegerCache.cache[i + (-IntegerCache.low)];  
  61.        return new Integer(i);  
  62.    }  

我想通过以上的分析,应该知道原因了吧,简要的说就是在Integer类中有一个静态内部类IntegerCache,在IntegerCache类中有一个Integer数组,用以缓存当数值范围为-128~127时的Integer对象。

注意:可以通过下面这个参数设置最大值

-XX:AutoBoxCacheMax

这个属性是在使用Oracle/Sun JDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN参数即可将Integer的自动缓存区间设置为[-128,NNN]。注意区间的下界固定在-128不可配置。 

在client模式下该参数无效。这个参数是server模式专有的,在c2_globals.hpp中声明,默认值是128;不过这个默认值在默认条件下不起作用,要手动设置它的值或者是开启-XX:+AggressiveOpts参数才起作用。

Cache to support the object identity semantics of autoboxing for values between

* -128 and 127 (inclusive) as required by JLS.

*

* The cache is initialized on first usage. The size of the cache

* may be controlled by the {@code -XX:AutoBoxCacheMax=} option.

* During VM initialization, java.lang.Integer.IntegerCache.high property

* may be set and saved in the private system properties in the

* sun.misc.VM class.

 

 

你可能感兴趣的:(Java)