题目一
第一部分
int a = 123;
int b = 123;
Integer c = 123;
Integer d = 123;
System.out.println(a == b);//true
System.out.println(a == c);//true
System.out.println(d == d);//true
在Java中,基本数据类型的比较使用的是值比较,而对象的比较默认使用的是引用比较。但是,Java对于值从-128到127之间的Integer对象做了特殊处理,它们会被自动缓存,所以当你创建这个范围内的Integer对象时,实际上会返回相同的引用。
这就是为什么以下代码中的比较都返回true
int a = 123;
int b = 123;
Integer c = 123;
Integer d = 123;
System.out.println(a == b); // true, 基本类型值比较
System.out.println(a == c); // true, `c`被自动拆箱为int类型,然后进行值比较。后文提到拆箱装箱
System.out.println(c == d); // true, `c`和`d`是在-128到127之间的Integer缓存引用
当比较的值超出这个范围,或者使用new Integer()创建对象时,相同值的Integer对象可能会有不同的引用,那么使用==进行比较就会返回false。在这种情况下,应该使用.equals()方法来比较对象的值。
第二部分
如果Integer的值是1280,那么即使两个Integer对象的值相同,使用==比较也会返回false。这是因为1280超出了Java自动缓存的-128到127的范围,所以每个Integer对象都会有不同的引用。
Integer x = 1280;
Integer y = 1280;
System.out.println(x == y); // 这将返回false
Integer x = 1280;
Integer y = 1280;
System.out.println(x.equals(y)); // 这将返回true
正确比较两个Integer对象的方法是使用.equals()方法,而不是==。这样可以比较对象的值,而不是它们的引用。
当处理大于127的Integer值时,始终使用.equals()方法来确保正确比较对象的值。
拆箱 装箱
装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
例如:
Integer i = 10; //装箱
int n = i; //拆箱
Java8种基本类型的自动装箱代码实现
//byte原生类型自动装箱成Byte
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
//short原生类型自动装箱成Short
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);
}
//char原生类型自动装箱成Character
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
//int原生类型自动装箱成Integer
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
//long原生类型自动装箱成Long
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);
}
//double原生类型自动装箱成Double
public static Double valueOf(double d) {
return new Double(d);
}
//float原生类型自动装箱成Float
public static Float valueOf(float f) {
return new Float(f);
}