Java基础-关于Integer的若干情况答复

我们都知道Interge是对Int基础类型的包装类。本着“万物皆对象”,这使一个Int类型能像一个对象一样去使用,并带有自己的方法。比如,在集合类中,我们是无法将int 、double等类型放进去的。因为集合的容器要求元素是Object类型。但是我们又不想因为Interge是封装类,而丢失之前int变量的方便操作:

int i=0; //难道每用一个Integer实例,就要 Integer i=new Integer(1);?
i++;     //++ += 操作难道要 每次都调用i.intValue();取出int基础变量进行操作?
i+=1;

所以在JDK1.5 以后引入语法糖—自动拆箱自动装箱,它的执行是在编译期,会根据代码的语法,在生成class文件的时候,决定是否进行拆箱和装箱动作。

1问— Iteger i=“1”;(自动装箱)

为什么可以写成:

 public static void main(String[] args) {
        Integer i=1;
    }

我们来看看编译后的class文件:
在这里插入图片描述
我们可以看到其实编译后,先采用iconst_1指令将常量1压入栈中。实际执行是INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;语句。就是我们执行的语句其实是(这里完成了一个自动装箱操作):

 public static void main(String[] args) {
        Integer i=Integer.valueOf(1);//这里完成了一个自动装箱操作
    }

2问— Integer的类++和+=操作 (自动拆箱、自动装箱)

测试代码:

  public static void main(String[] args) {
        Integer i=1;
        i++;
        i+=1;
    }

同理我们看看编译后文件:

 // access flags 0x9
  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 4 L0
    ICONST_1     
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    ASTORE 1
   L1                                                  //这里是i++代码块
    LINENUMBER 5 L1
    ALOAD 1
    ASTORE 2
    ALOAD 1
    INVOKEVIRTUAL java/lang/Integer.intValue ()I      //1.这里进行一个拆箱,取到int值
    ICONST_1                                          //2.取到的int压入栈中
    IADD                                              //3.完成+1操作
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;//4.再次装箱,将int转成integer
    DUP
    ASTORE 1
    ASTORE 3
    ALOAD 2
    POP
   L2                                                //这里是+=操作,同理
    LINENUMBER 6 L2
    ALOAD 1
    INVOKEVIRTUAL java/lang/Integer.intValue ()I
    ICONST_1
    IADD
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    ASTORE 1
		 .
		 .
		 .
}

上面的注解就解释了,而Integer.intValue ()就是返回Integer实例中的int值。所以这就是在++、+=操作下拆箱、装箱的具体实现。

3问—Integer==int(自动拆箱)

演示代码:

  public static void main(String[] args) {
        Integer integer=128;
        int i_1=-128;
        int i_2=128;
        System.out.println(integer == i_1);
        System.out.println(integer == i_2);
    }

结果很明显是:

false
true

因为我们知道"==“对基础数据类型就是判断是否相等,对引用对象就是判断引用地址是否一致。但这里是"引用”==基础变量,那最后是怎么完成的呢:

//这里是"integer == i_1"编译代码块
    LINENUMBER 7 L3
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 1
    INVOKEVIRTUAL java/lang/Integer.intValue ()I //我们可以看到还是进行了拆箱,获取int值。
    ILOAD 2
    IF_ICMPNE L4  //完成比较
    ICONST_1
    GOTO L5

所以这里是进行了自动拆箱。

4问—Integer==Integer 问题

上面一问,我们就知道了"=="对“Integer”==“Integer”这类引用的比较会进行地址比较,那木下面代码呢:

 public static void main(String[] args) {
        Integer a_1=127;
        Integer a_2=127;
        Integer b_1=-128;
        Integer b_2=-128;
        Integer c_1=-129;
        Integer c_2=-129;
        System.out.println(a_1==a_2);
        System.out.println(b_1==b_2);
        System.out.println(c_1==c_2);
    }

答案却是:

true
true
false

为什么呢,在这 Integer a_1=127; 我们知道是进行装箱的,会调用valueOf(int i)方法的,那我们去看看这个方法:
在这里插入图片描述
明显的是i进去以后,会先进行一个判断,若在[-128,127]区间,就会直接返回IntegerCache.cache数组相应下表的位置。(对于IntegerCache将在下面给出解释) 所以这就是为什么a系列和b系列会判ture,而c系列是false,因为c系列两值进去等会new 一个新对象,那么他们两分配的地址也就不可能相等了。
拓展
为提高效率和性能,引入了一个IntegerCache来节省内存和提高性能。整型对象通过使用相同的对象引用实现了缓存和重用。
在这里插入图片描述
其他包装类一样,但为什么是[-128,127]区间?
因为1字节=8位(bit)。java中的整型属于有符号数。

8bit可以表示的数字:
最小值:10000000 (-128(-2^7)
最大值:01111111127(2^7-1)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值