我们先来看一下下面这两个例子
public class IntegerDemo {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
int c = 100;
Integer d = new Integer(100);
Integer e = Integer.valueOf(100);
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);
System.out.println(a == e);
System.out.println(c == d);
System.out.println(c == e);
}
}
public class IntegerDemo {
public static void main(String[] args) {
Integer a = 200;
Integer b = 200;
int c = 200;
Integer d = new Integer(200);
Integer e = Integer.valueOf(200);
Integer f = new Integer(200);
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);
System.out.println(a == e);
System.out.println(c == d);
System.out.println(c == e);
System.out.println(d == f);
}
}
看到这里,我们不经需要发出灵魂拷问,为什么仅仅改变了int的值,执行的结果就不太一样了
我们来我们使用javap -v命令这个类的class文件,看看以不同的形式定义Integer对象,底层都是怎么处理的
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=7, args_size=1
0: bipush 100
2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: bipush 100
8: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
11: astore_2
12: bipush 100
14: istore_3
15: new #3 // class java/lang/Integer
18: dup
19: bipush 100
21: invokespecial #4 // Method java/lang/Integer."<init>":(I)V
24: astore 4
26: bipush 100
28: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
31: astore 5
33: new #3 // class java/lang/Integer
36: dup
37: bipush 100
39: invokespecial #4 // Method java/lang/Integer."<init>":(I)V
42: astore 6
44: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
47: aload_1
48: aload_2
49: if_acmpne 56
52: iconst_1
53: goto 57
56: iconst_0
57: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
60: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
63: aload_1
64: invokevirtual #7 // Method java/lang/Integer.intValue:()I
67: iload_3
68: if_icmpne 75
71: iconst_1
72: goto 76
75: iconst_0
76: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
79: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
82: aload_1
83: aload 4
85: if_acmpne 92
88: iconst_1
89: goto 93
92: iconst_0
93: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
96: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
99: aload_1
100: aload 5
102: if_acmpne 109
105: iconst_1
106: goto 110
109: iconst_0
110: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
113: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
116: iload_3
117: aload 4
119: invokevirtual #7 // Method java/lang/Integer.intValue:()I
122: if_icmpne 129
125: iconst_1
126: goto 130
129: iconst_0
130: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
133: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
136: iload_3
137: aload 5
139: invokevirtual #7 // Method java/lang/Integer.intValue:()I
142: if_icmpne 149
145: iconst_1
146: goto 150
149: iconst_0
150: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
153: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
156: aload 4
158: aload 6
160: if_acmpne 167
163: iconst_1
164: goto 168
167: iconst_0
168: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
171: return
我们着重来看一下main方法这一段
Integer a = 100;对应着这段代码
0: bipush 100 2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: astore_1
从这段代码可以看出来,Java是使用Integer.valueOf来实现自动装箱的
int和Integer进行比较时,会自动拆箱,转成int比较值,英雌,int和对应的包装类Integer是相等的,这个比较简单,就不过多分析了,我们来着重分析一下new Integer(value)和Integer.valueOf(value)
public Integer(int value) {
this.value = value;
}
static final int low = -128;
static final int high;(默认127)
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
我们看出来使用valueOf方法时,在-128到127之间,会使用缓存,而使用new时,会直接创建一个新的对象,因此当int的值在-128到127之间,并且使用Integer.valueOf(包括自动装箱)方法创建对象时,使用==比较对象是相等的,使用new关键字会创建一个新的对象,因此==比较地址不相等
其他基本数据类型
我们子阿来看一下其他基本类型
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
public static Float valueOf(float f) {
return new Float(f);
}
public static Double valueOf(double d) {
return new Double(d);
}
我们看到,除了Float和Double,其他基本类型的包装类,在-128到127之间都有缓存,因此,我们在比较的时候,需要注意