int和Integer有什么区别?

这个问题看起来比较简单,可以问的问题可多可少。
一般常见的考察范围是java的基础数据类型和包装类。然后可以延伸到自动拆箱和自动装箱以及包装类中的缓存和缓存范围。当然还可以延伸到设计模式–享元模式等。
首先比较典型的回答:

  • Integer是int的包装类,int是基础数据类型
  • Integer变量必须实例化后才能使用,int变量不需要
  • Integer是对象的引用,指向new出Integer对象,int直接存储数据值
  • Integer默认值是null,int的默认值是0

1.由于Integer变量是两个对象的引用,所以new出Integer是两个对象,永远不相等

Integer a = new Integer(2);
Integer b = new Integer(2);
System.out.println(a==b);//false

2.Integer一个被new出来,一个直接赋值。结果也不相等。

Integer a = new Integer(2);
Integer c = 2;
System.out.println(a==c);//false

这是对象c是怎样产生的呢,我们可以通过编译javac和反编译javap -c来查看一下。

public class IntegerTest {
    public static void main(String[] args) {

        Integer a = new Integer(2);
        Integer c = 2;
        System.out.println(a==c);
    }
}
public class com.zktravel.IntegerTest {
  public com.zktravel.IntegerTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":
()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/Integer
       3: dup
       4: iconst_2
       5: invokespecial #3                  // Method java/lang/Integer."<init>"
:(I)V
       8: astore_1
       9: iconst_2
      10: invokestatic  #4                  // Method java/lang/Integer.valueOf:
(I)Ljava/lang/Integer;
      13: astore_2
      14: getstatic     #5                  // Field java/lang/System.out:Ljava/
io/PrintStream;
      17: aload_1
      18: aload_2
      19: if_acmpne     26
      22: iconst_1
      23: goto          27
      26: iconst_0
      27: invokevirtual #6                  // Method java/io/PrintStream.printl
n:(Z)V
      30: return
}

我们在第10行可以看出,是通过Integer.valueOf实例化的变量。这时我们再看下Integer.valueOf()这个方法。

public static Integer valueOf(int i) {
       if (i >= IntegerCache.low && i <= IntegerCache.high)
           return IntegerCache.cache[i + (-IntegerCache.low)];
       return new Integer(i);
   }

可以看出如果int i在缓存中池使用缓存池的对象,如果不在就new一个。
3.如果两个Integer都是非new出来的进行比较时,如果两个变量的值在-128到127之间,两个值相等。如果不在-128到127之间,则不相等。

public static void main(String[] args) {

        Integer a = 2;
        Integer c = 2;
        System.out.println(a==c);//true

        Integer b = 128;
        Integer d = 128;
        System.out.println(b==d);//false
    }

由上面Integer.valueOf可以如果不在缓存范围内就会new Integer。所有b和d不相等。
4.如果是Integer变量与int变量比较时,只要两个变量的值相等,就相等。因为包装类Integer与基础类型int比较时,包装类会自动拆箱为int,然后进行比较。最后就是两个int变量的比较了。

public static void main(String[] args) {

        Integer a = 2;
        int c = 2;
        System.out.println(a==c);//true

        Integer b = 128;
        int d = 128;
        System.out.println(b==d);//true
    }

通过javac编译和javap -c反编译后可以看到:

public com.zktravel.IntegerTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":
()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_2
       1: invokestatic  #2                  // Method java/lang/Integer.valueOf:
(I)Ljava/lang/Integer;
       4: astore_1
       5: iconst_2
       6: istore_2
       7: getstatic     #3                  // Field java/lang/System.out:Ljava/
io/PrintStream;
      10: aload_1
      11: invokevirtual #4                  // Method java/lang/Integer.intValue
:()I
      14: iload_2
      15: if_icmpne     22
      18: iconst_1
      19: goto          23
      22: iconst_0
      23: invokevirtual #5                  // Method java/io/PrintStream.printl
n:(Z)V
      26: sipush        128
      29: invokestatic  #2                  // Method java/lang/Integer.valueOf:
(I)Ljava/lang/Integer;
      32: astore_3
      33: sipush        128
      36: istore        4
      38: getstatic     #3                  // Field java/lang/System.out:Ljava/
io/PrintStream;
      41: aload_3
      42: invokevirtual #4                  // Method java/lang/Integer.intValue
:()I
      45: iload         4
      47: if_icmpne     54
      50: iconst_1
      51: goto          55
      54: iconst_0
      55: invokevirtual #5                  // Method java/io/PrintStream.printl
n:(Z)V
      58: return

Integer变量先通过Integer.valueOf初始化,然后再通过Integer.intValue拆箱转化为int。

下面再通过Integer的源码再看一下。

public final class Integer extends Number implements Comparable<Integer> {}
  • Integer被定义为final,是不能继承的
  • Integer继承了Number类,所以可以调用Number中intValue、longValue等方法返回对应类型的值。
  • 实现了Comparable接口,就可以使用compareTo进行对象的比较

上面用到Integer.valueOf(),先判断传入的值是否在缓存范围内,如果在缓存范围内(默认-128到127),则指向缓存池中的对像,如果不在就new一个。

public static Integer valueOf(int i) {
       if (i >= IntegerCache.low && i <= IntegerCache.high)
           return IntegerCache.cache[i + (-IntegerCache.low)];
       return new Integer(i);
   }

默认的最低是-128,最大是127.

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) {
               try {
                   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);
               } catch( NumberFormatException nfe) {
                   // If the property cannot be parsed into an int, ignore it.
               }
           }
           high = h;

           cache = new Integer[(high - low) + 1];
           int j = low;
           for(int k = 0; k < cache.length; k++)
               cache[k] = new Integer(j++);

           // range [-128, 127] must be interned (JLS7 5.1.7)
           assert IntegerCache.high >= 127;
       }

       private IntegerCache() {}
   }

当然这里可以通过设置jvm启动值改变最大值size。

 -XX:AutoBoxCacheMax=size

Integer提供了两个构造方法:

//构造一个新分配的 Integer 对象,它表示指定的 int 值。
public Integer(int value) {
     this.value = value;
 }

//构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
 }

其中parseInt方法第一个参数是值,第二个是基数,默认是10进制。
其他还可能是16进制,2进制,8进制等。

Integer还提供了valueof转化String为Integer的方法。同样是先使用parseInt()先进行转换,然后再使用Integer.valueOf进行转换(默认使用10进制)。如下:

public static Integer valueOf(String s) throws NumberFormatException {
       return Integer.valueOf(parseInt(s, 10));
   }
public static Integer valueOf(String s, int radix) throws NumberFormatException {
      return Integer.valueOf(parseInt(s,radix));
  }

Integer提供的toString方法比较简单。但是里面的实现方式很值得学习。

public static String toString(int i) {
//这里先对i的值做检验,如果等于Int能表示的最小值,则直接返回最小值的字符串形式
        if (i == Integer.MIN_VALUE)
        //这里直接返回最小值,因为下面的方法最大只能返回2147483647
            return "-2147483648";
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
    }

通过stringsize()可以了解第一步先返回最小值的原因。

 final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

    // Requires positive x
    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }

因为如果是负数,需要先转化为整数,进行+1传入。多的一位用了存储负号。整数的最大值只有2147483647。
sizeTable为数组,设置了范围。基于范围的查找,性能上有优势。
getChars()主要是进行了移位和乘法操作。
最后使用string构造函数返回String.

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值