在一个公众号上看到一道面试题,由此引出对Integer类中的valueOf方法的探究。Integer类中的valueOf源码如下:
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
可以看出,调用valueOf方法后,每次返回都是一个全新的对象。
public static void main(String[] args) {
Integer a = new Integer(10);
/**
* 为给定对象返回与默认方法hashCode()返回相同的哈希代码,不管给定对象的类是否重写hashCode()。
* native方法,应该是根据对象在内存中的地址,计算hashCode
* Integer中的hashCode()已被重写,直接返回value
* s和s2不同,说明已不是同一个对象
* s2和s3相同,说明仍是同一个对象,意为赋值,只是引用关系的改变
*/
int s = System.identityHashCode(a);
System.out.println(s); //7461949 7896426
/**
* Integer中的toString()已经被重写
*/
System.out.println(a.toString());
a = Integer.valueOf(a.intValue());
int s2 = System.identityHashCode(a);
System.out.println(s2); //23414511 20079748
Integer b = a;
int s3 = System.identityHashCode(b);
System.out.println(s3);
}
通过System.identityHashCode()方法更能说明,经过拆箱,装箱,虽然值相同,但早已不是同一个对象。
下来再看那道面试题:
public class MyRunnable implements Runnable{
public static Integer i = new Integer(0);
@Override
public void run() {
while(true){
synchronized (i) {
if(i < 100){
/**
* i = i + 1;
* 拆箱 i=i.intValue();
* 进行计算 i+1
* 装箱 Integer valueOf = Integer.valueOf(i+1);
* 赋值 i = valueOf;
* 每次返回都是一个新的对象,相当于没加锁
*/
/*public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}*/
i ++;
System.out.println("i = " + i);
} else {
break;
}
}
}
}
/**
* 结果并不是乱序1..100那么简单。
* i = 1
i = 3
i = 3
i = 4
i = 5
...
* @param args
*/
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable());
Thread t2 = new Thread(new MyRunnable());
t1.start();
t2.start();
}
}
题目如上,问:最后的输出结果是什么?
结果与分析已经作为备注写在了代码上。很小的问题,结果却并不是一眼看去的那么简单。
引申一下:
我们知道,判断两个对象相等,需要重写hashCode和equals方法,事实上,Integer类中的hashCode和equals方法都已被重写。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
public int hashCode() {
return value;
}
即最终比较的都是Integer的value值,返回的hashCode也是Integer的value值。