java面试一道令人怀疑人生的java面试题
题目比较简单,写一个swap方法,交换两个Integer的值。
方法一
使用中间变量直接交换
private static void swap(Integer num1,Integer num2){ Integer tmp = num1; num1 = num2; num2 = tmp; }当然,如果仅仅按照以上方结果是不能交换的值,因为num1与num2是局部变量,方法结束后值还是没有变,除非有相应的返回值来解决。
方法二
使用反射
private static void swap(Integer num1,Integer num2){ // Integer tmp = num1; // num1 = num2; // num2 = tmp; try { Field field = Integer.class.getDeclaredField("value"); field.setAccessible(true); int tmp = num1;//拆箱 field.set(num1,num2); field.set(num2,tmp); } catch (Exception e) { e.printStackTrace(); } }如上所示,但是结果还是不是我们预期的,结果如下
是什么原因导致的呢?打开Integer的源码如下:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }我们发现,Interger取值时是首先判断IntegerCache,而IntegerCache值的范围是[-128]-[127],当我们 field.set(num1,num2)时,IntegerCache中对应num1的位置是IntegerCache[129],即IntegerCache[129]的值被改为2,而执行到 field.set(num2,tmp)时,会对tmp进行装箱操作,但是tmp的值同样在[-128]-[127],即会去取IntegerCache[129]的值,而此时IntegerCache[129]的值为2,所以field.set(num2,tmp)后num2的值还是2. 要解决上面出现的问题目前有两种方法:方法一 在使用tmp是重新new一个新对象,即field.set(num2,new Integer(tmp))。
private static void swap(Integer num1,Integer num2){ // Integer tmp = num1; // num1 = num2; // num2 = tmp; try { Field field = Integer.class.getDeclaredField("value"); field.setAccessible(true); int tmp = num1;//拆箱 field.set(num1,num2); field.set(num2,new Integer(tmp)); } catch (Exception e) { e.printStackTrace(); } }
方法二、直接将值作为一个int类型,不进行拆装箱操作即field.setInt(num2,tmp);
private static void swap(Integer num1,Integer num2){ // Integer tmp = num1; // num1 = num2; // num2 = tmp; try { Field field = Integer.class.getDeclaredField("value"); field.setAccessible(true); int tmp = num1;//拆箱 field.set(num1,num2); field.setInt(num2,tmp); } catch (Exception e) { e.printStackTrace(); } }