Integer类中的valueOf方法

在一个公众号上看到一道面试题,由此引出对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值。

你可能感兴趣的:(JDK&JVM)