与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() 比较的是 " 堆 " 中的内容。