int那小点关系

(本文章是小弟在学习java过程中的一点小心得,要是有说得不对的地方,望给各位大侠指点
Integer
int
的封装类,是一个类,用
Integer
声明一个变量时,其是一个对象类型(或者说引用类型);
int
是基本类型,用
int
声明的变量是非对象类型,即不能在其上调用方法(如
equals()
)。“
==
”作用于对象上的时候,其比较的是对象的引用本身的值,当比较的是基本数据类型时,比较的是值。即“
==
”比较的是栈(
stack
)中的引用或值:
例如:
public
class IntDome {
  
public
static
void main(String[] args) {
    
int int1 = 12;
    Integer int2 = 12;
    Integer int3 =
new Integer(12);
    System.out.println(
"***********************");
    
if (int2 == int1) {
      System.out.println(
"int2==int1: true");
    }
else {
      System.out.println(
"int2!=int1: false");
    }
    
if (int2.equals(int1)) {
      System.out.println(
"int2.equals(int1): true");
    }
else {
      System.out.println(
"int2.equals(int1): false");
    }
    System.out.println(
"***********************");
    
if (int3 == int1) {
      System.out.println(
"int3==int1: true");
    }
else {
      System.out.println(
"int3!=int1: false");
    }
    
if (int3.equals(int1)) {
      System.out.println(
"int3.equals(int1): true");
    }
else {
      System.out.println(
"int3.equals(int1): false");
    }
    System.out.println(
"***********************");
    
if (int2 == int3) {
      System.out.println(
"int2==int3: true");
    }
else {
      System.out.println(
"int2!=int3: false");
    }
    
if (int2.equals(int3)) {
      System.out.println(
"int2.equals(int3): true");
    }
else {
      System.out.println(
"int2.equals(int3): false");
    }
    System.out.println(
"***********************");
  }
}
***********************

int2==int1: true

***********************

int3==int1: true

int3.equals(int1): true

***********************

***********************
int3==int1: true
因为
int2
向下转型为
int
型,
Integer.intValue(int2)=int1, Integer.intValue(int3)=int1,
而此时它们的数值又相等,因此返回真。

int2.equals(int1): true
int3.equals(int1): true
首先
equals
只能用于对象,因此基本类型不能调用它,即不能写
int1.equals
int2
)或者
int1.equals
int3
;为什么会返回真呢?在
jdk1.5
中引入的自动装箱和自动拆箱,那么,
int1
会被自动打包成
Integer(int1);
int2.equals();
int2
在声明时,直接赋予
12
,但是其实在编译时是这样的
Integer int2 = Integer.
valueOf(12);

我们可以反编译看一下(
javap –c intDome
):

  public static void main(java.lang.String[]);

    Code:

       0: bipush        12

       2: istore_1             //0~2
int int1 = 12;

       3: bipush        12

       5: invokestatic  #2                  // Methodjava/lang/Integer.valueOf:

(I)Ljava/lang/Integer;

       8: astore_2                    //3~5
Integer int2 = 12;
可以发现他调用了
Integer.valueOf()
方法。即就是
Integer int2 = Integer.
valueOf(12);

       9: new           #3                  // class java/lang/Integer

      12: dup

      13: bipush        12

      15: invokespecial #4                  // Method java/lang/Integer."<init>"

:(I)V

      18: astore_3                        //9~18
Integer int3 = new Integer(12);
以下的就是输出语句了。

      19: getstatic     #5                  // Field java/lang/System.out:Ljava/

io/PrintStream;

      22: ldc           #6                  // String ***********************

            24: invokevirtual #7                  // Method java/io/PrintStream.printl

n:(Ljava/lang/String;)V

      27: aload_2

      28: invokevirtual #8                  // Method java/lang/Integer.intValue          //
调用了
Integer.intValue(int2)
返回一个基本
                    
数据类型
int
数值,所以
int2==int1: true

:()I

      31: iload_1

      32: if_icmpne     46

      35: getstatic     #5                  // Field java/lang/System.out:Ljava/

io/PrintStream;

      38: ldc           #9                  // String int2==int1: true

  . . . . . . . . . . . .

注:红字是解释。

int2!=int3: false
之所以返回
false
是因为
int2
被打包后,在堆中开辟了一个新的空间,并把地址引用给栈,因此两个对象在栈中的引用不同。但有一种情况要注意,看一下下面实例:

public class TestDome {

    public static void main(String[] args) {

        Integer i1 = 2;

        Integer i2 = 2;

        Integer i3 = 128;

        Integer i4 = 128;

        System.out.println("i1 == i2: "+(i1 == i2));

        System.out.println("i3 == i4: "+(i3 == i4));

    }

}

运行结果:

i1 == i2: true

i3 == i4: false

为什么会出现这样的情况?当
2
128
被自动打包时,要调用
Integer.valueOf()
方法。我们来看一下此方法:

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);
}
又因为
IntegerCache
缓存了
[-128,127]
之间的
Integer
对象,如果参数
i
介于
-128~127
之间,就返回缓存的对象。否则就
new
一个新的
Integer
。而“
==
”作用于对象上的时候,其比较的是对象的地址(栈中的值
(
引用
)
),例子中的
i1,i2
都是从缓存中拿的,当然是同一个对象,
i3
i4
都是通过
new Integer
获得的,当然不是同一个对象了。

类似地,
java.lang.Long
java.lang.Short
分别缓存了
[-128,127]
之间的
Long
Short
对象,
java.lang.Byte
缓存了所有的对象,
java.lang.Character
缓存了
[0,127]
之间的
Character
对象。
java
缓存这些对象是为了性能优化

int2.equals(int3): true
因为它们在堆中存放的内容相同,所以返回
true

 
 
附:
==
equals
区别

       
==
可用于基本类型和引用类型:当用于基本类型时候,是比较值是否相同;当用于引用类型的时候,是比较对象是否相同。
"=="
比较变量时
,
系统使用变量在
"
"
中所存的值作为比较的依据。基本数据类型在
"
"
中存的是其内容值
,
而对象类型在
"
"
中存的是地址
,
这些地址指向
"
"
中的对象。
"=="
"!="
比较的是
"
"
中的内容
,
equals()
比较的是
"
"
中的内容。