关于java的活动拆装箱若干细节问题。java自动拆装箱。

一样、首先需要了解之几单前提:

一致、自动拆装箱


    自动装箱过程就是通过调用valueOf方法实现(如:Integer.valueOf(10)),而拆箱过程即是调用xxxValue方法实现(如Integer.intValue())。

活动拆装箱:

Integer a = 10;//自动装箱 –>  Integer a = Integer.valueOf(10);

int b = a; //自动拆箱 –> int b = a.intValue();

1、自动装箱过程是经调用valueOf方法实现(如Integer.valueOf(10)),而拆箱过程是通过调用包装器的
xxxValue方法实现(如Integer.intValue(a))。

二、缓存


Integer,Short,Long,Byte,Character包装类型有缓存机制(cache数组)。

Boolean类型有TRUE和FALSE两只静态成员。

    public static final Boolean TRUE = new Boolean(true);

*    public static final Boolean FALSE = new Boolean(false);*

Double和Float没有缓存机制。

诸如代码:

三、“==” 和“equals”比较(重点)


 Integer有一个静态方法valueOf(int
i),当自动装箱触发时,编译器会活动补充调用该方法的代码。

Integer的valueOf(int i)源码如下:

public static Integer valueOf(int i) {    final int offset = 128;

*      if (i >= -128 && i <= 127) { // must cache*

*            return IntegerCache.cache[i + offset];*

*      }*

*      return new Integer(i);*

*    }*

“==”运算符是用来比基本项目变量和援类型变量。

        Integer a = 1;
        a++;

1、当2只操作数都是包档次变量是,比较的是看它是不是对同一个对象(既比较地址是否一律)

假如:Integer a = 1;    –>会活动装箱,即调用valueOf(1);

Integer b = 1;      –>会活动装箱,即调用valueOf(1);

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

地方的Integer a = 1;  和  Integer b =
1;因为1以-128-127内,所以装箱后底Integer指向同一个地点,即 a ==
b返回true。若无当-128 –
127之间,这会new对象下。new出来的目标,地址是不同之。

只要:Integer a = 300;     –>会自行装箱,即调用valueOf(300);

Integer b = 300;      –>会自动装箱,即调用valueOf(300);

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

其二自行装箱和拆箱的过程如下:

2、如果中有一个操作数是表达式(既涵盖算术运算)则会预先进行活动拆箱,再开展对应之着力项目变量比较。

如:

int i = 3;

Integer a = 1;

Integer b = 2;

System.out.println(i == (a+b))       //true 
分别对a和b进行了活动拆箱操作,然后再度add运

                                                         //
算,之后再行跟i进行较,属于数值比较。

如:

Integer a = 1;

Integer b = 2;

Integer c = 3;

System.out.println(c == (a+b))     //true 
分别对a,b和c进行了机动拆箱操作,之后再度展开

                                                       // 数值比。

必威 1

3、基本包装档次又写了equals方法,基本包装档次的equals不会见展开路的变,类型不同之包裹档次的变量直接判断为false,尽管她们之数值或是当的。

如:

Integer a = 1;

Long b = 1;

System.out.println(a.equals(b))     //false  包装档次不同,直接false

如:

Integer a = 300;

Integer b = 300;

System.out.println(a.equals(b))     //true   
包装档次相同,再判断数值,此处的a==b 是false

 0: iconst_1
 1: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

 4: astore_1
 5: aload_1
 6: invokevirtual #22                 // Method java/lang/Integer.intValue:()I
 9: iconst_1
10: iadd
11: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

季、代码练习


必威 2

答案:

必威 3

必威 4

五、其他类型转换为Integer对象

俺们还晓得创建一个Integer对象是

    Integer integer_1 = new Integer(10);

这就是说Inter还有什么其他方法呢?

1) 把int转成Integer对象

    Integer integer_2 = Integer.valueOf(10);

2) 把String转出Integer对象

    Integer integer_3 = Integer.valueOf(“10”);

3) 把String转出int

    int a = Integer.parseInt(“10”);

4) System.out.println(integer_1 == integer_2);            
 ////判断的凡引用的地点,结果为false

2、缓存

Integer、Short、Byte、Character、Long包装类型有缓存机制(cache数组)。

Boolean类型有TRUE 和 FALSE两独静态成员。

必威 5

    public static final Boolean TRUE = new Boolean(true);

    /** 
     * The <code>Boolean</code> object corresponding to the primitive 
     * value <code>false</code>. 
     */
    public static final Boolean FALSE = new Boolean(false);

必威 6

Double和Float没有缓存机制。

老二、关键的总结写在面前

1、 我们懂得,”==”运算符既可用来比基本项目变量和援类型变量。当半独操作数都是包装器类型的变量时,判定标准也她们是否针对同一个对象;而设内部有一个操作数是表达式(即含算术运算)则会优先进行机动拆箱,再拓展对应基本类型变量比较。

2、基本包装档次又写了equals方法,基本包装档次的equals不见面开展项目的换,类型不同之卷入档次的变量直接为判定为false,尽管他们的数值产生或是当的。

老三、从平段代码开始

必威 7

package com.demo;
public class Interview {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int i = 3;
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 250;
        Integer f = 250;
        Long g = 3L;
        Long h = 2L;

        System.out.println(i==(a+b));
        System.out.println(c==d);
        System.out.println(e==f);
        System.out.println(c.equals(d));
        System.out.println(e.equals(f));
        System.out.println(c==(a+b));
        System.out.println(c.equals(a+b));
        System.out.println(g==(a+b));
        System.out.println(g.equals(c));
        System.out.println(g.equals(a+b));
        System.out.println(g.equals(a+h)); 
    }
}

必威 8

 

季、运行结果

必威 9必威 10

true
true
false
true
true
true
true
true
false
false
true

View Code

五、后面的分析出硌长

拿如达到代码编译后底class文件进行javap反汇编,基本会证明大部分的题材。

第一处:

System.out.println(i==(a+b));

尽过程如下:

 61: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 64: aload_3
 65: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 68: iadd
 69: if_icmpne     76

证明分别对a和b进行了机动拆箱操作,然后还add运算,之后再跟i进行比较,属于数值比。

第二处:

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

是大家都懂得,在针对3同3展开自动装箱成c和d时,直接由Integer的休养生息存数组cache中获得一致的对象引用,因此==判定返回true。

Integer的valueOf(int i)源码如下:

必威 11

public static Integer valueOf(int i) {
    final int offset = 128;
    if (i >= -128 && i <= 127) { // must cache 
        return IntegerCache.cache[i + offset];
    }
        return new Integer(i);
 }

必威 12

第三处:

System.out.println(e==f);

与亚地处不同之是,将250自动装箱时,不以-128及127中,实际上是new了一定量只不同之目标。

调用了少潮如下的Integer的构造器,尽管传入的参数value都是250,但是确是见仁见智的目标。因此==判定返回false。

    public Integer(int value) {
      this.value = value;
    }

季处在和第五地处:

        System.out.println(c.equals(d));
        System.out.println(e.equals(f));

马上有限介乎和第二及老三高居形成对比,主要的界别是Integer重写了从Object继承下来的equals方法。

Object的equals源码如下,简单干净,纯粹等同于对象的==比较:

    public boolean equals(Object obj) {
    return (this == obj);
    }

Integer的equals源码如下:

    public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
    }

好窥见,如果obj如果符合instanceof判定,那么会用obj自动拆箱,实际比的是零星个Integer对象的数值。

当下就算讲了虽然e和f是不同之目标(==判定为false),但是equals判定为true,因为其数值还也250。

第六处:

System.out.println(c==(a+b));

行进程如下:

必威 13

 145: aload         4
 147: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 150: aload_2
 151: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 154: aload_3
 155: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 158: iadd
 159: if_icmpne     166

必威 14

得视对a、b和c都调用Integer.intValue()方法开展自动拆箱,最终于的依然是数值必威,因此归true。

第七处:

System.out.println(c.equals(a+b));

实践进程如下:

必威 15

 173: aload         4
 175: aload_2
 176: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 179: aload_3
 180: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 183: iadd
 184: invokestatic  #23                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

 187: invokevirtual #52                 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z

必威 16

足见见其过程为:先对a和b进行活动拆箱,再进行add运算后,再对运算结果进行活动装箱,最后调用Integer.equals()方法开展判断,而equals判定最终于的尚是累组,因此归true。

第八处:

System.out.println(g==(a+b));

彼行结果如下:

必威 17

196: aload         8
198: invokevirtual #55                 // Method java/lang/Long.longValue:()J
201: aload_2
202: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
205: aload_3
206: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
209: iadd
210: i2l
211: lcmp

必威 18

暨第六介乎的法则基本类似,都是展开自动拆箱,只不过这里g是调整用Long.longValue()方法拆箱。

第九处:

System.out.println(g.equals(c));

斯地方应该特别注意,观察Integer的equals源码不难发现,equals判定的首先步是进展instanceof判定,显然c不是Long的实例,判定失败,直接归false。

也就是说这里素有无展开数值比较的时机。

因此,基本包装档次的equals不会见进行项目的转换,类型不同之包裹档次对象直接被判定为false,尽管她们的数值产生或是相等的。

第十处:

System.out.println(g.equals(a+b));

实践过程如下:

必威 19

 239: aload         8
 241: aload_2
 242: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 245: aload_3
 246: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 249: iadd
 250: invokestatic  #23                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

 253: invokevirtual #59                 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z

必威 20

眼看实在是第九地处的扩展。

不难看出,其尽进程吧:先对a和b进行机动拆箱,进行add运算,在对结果进行自动装箱,再拓展equals判定。

但add运算的结果机关装箱后还是是Integer类型,由第九处于不过了解,自然会被判定为false。

第十一地处:

System.out.println(g.equals(a+h)); 

履行进程如下:

必威 21

 262: aload         8
 264: aload_2
 265: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
 268: i2l
 269: aload         9
 271: invokevirtual #55                 // Method java/lang/Long.longValue:()J
 274: ladd
 275: invokestatic  #31                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
 278: invokevirtual #59                 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z

必威 22

及第十处不同之处在于,a和h自动拆箱后进行add运算的会向上转型也long类型,在针对那个自行装箱后自会叫装进成Long类型。

而且,两个比对象的数值相等,自然会于判定为true。

六、最后附上完整的反编译代码

必威 23必威 24

D:\java\qcworkspace\test\bin\com\demo>javap -c Interview
警告: 二进制文件Interview包含com.demo.Interview
Compiled from "Interview.java"
public class com.demo.Interview {
  public com.demo.Interview();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_3
       1: istore_1
       2: iconst_1
       3: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

       6: astore_2
       7: iconst_2
       8: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

      11: astore_3
      12: iconst_3
      13: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

      16: astore        4
      18: iconst_3
      19: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

      22: astore        5
      24: sipush        250
      27: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

      30: astore        6
      32: sipush        250
      35: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

      38: astore        7
      40: ldc2_w        #22                 // long 3l
      43: invokestatic  #24                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      46: astore        8
      48: ldc2_w        #29                 // long 2l
      51: invokestatic  #24                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      54: astore        9
      56: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
      59: iload_1
      60: aload_2
      61: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
      64: aload_3
      65: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
      68: iadd
      69: if_icmpne     76
      72: iconst_1
      73: goto          77
      76: iconst_0
      77: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
      80: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
      83: aload         4
      85: aload         5
      87: if_acmpne     94
      90: iconst_1
      91: goto          95
      94: iconst_0
      95: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
      98: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     101: aload         6
     103: aload         7
     105: if_acmpne     112
     108: iconst_1
     109: goto          113
     112: iconst_0
     113: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     116: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     119: aload         4
     121: aload         5
     123: invokevirtual #47                 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z
     126: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     129: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     132: aload         6
     134: aload         7
     136: invokevirtual #47                 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z
     139: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     142: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     145: aload         4
     147: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     150: aload_2
     151: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     154: aload_3
     155: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     158: iadd
     159: if_icmpne     166
     162: iconst_1
     163: goto          167
     166: iconst_0
     167: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     170: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     173: aload         4
     175: aload_2
     176: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     179: aload_3
     180: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     183: iadd
     184: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

     187: invokevirtual #47                 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z
     190: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     193: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     196: aload         8
     198: invokevirtual #51                 // Method java/lang/Long.longValue:()J
     201: aload_2
     202: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     205: aload_3
     206: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     209: iadd
     210: i2l
     211: lcmp
     212: ifne          219
     215: iconst_1
     216: goto          220
     219: iconst_0
     220: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     223: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     226: aload         8
     228: aload         4
     230: invokevirtual #55                 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
     233: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     236: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     239: aload         8
     241: aload_2
     242: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     245: aload_3
     246: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     249: iadd
     250: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

     253: invokevirtual #55                 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
     256: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     259: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
     262: aload         8
     264: aload_2
     265: invokevirtual #37                 // Method java/lang/Integer.intValue:()I
     268: i2l
     269: aload         9
     271: invokevirtual #51                 // Method java/lang/Long.longValue:()J
     274: ladd
     275: invokestatic  #24                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     278: invokevirtual #55                 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
     281: invokevirtual #41                 // Method java/io/PrintStream.println:(Z)V
     284: return
}

View Code

告。。。。好长。终于结束了。

转载注明:http://www.cnblogs.com/qcblog/p/7670159.html 

相关文章