面试题 -关于Integer(-128~127范围内)的交换

ー:题目如下

public class IntegerSwapTest {
     public static void main ( String [] args ) {
         Integer a = 1 ;
         Integer b = 2 ;
         System . out . println ( "before swap: a=" + a + ",b=" + b );
        
         swap ( a , b );
         System . out . println ( "after swap: a=" + a + ",b=" + b );
    }
     // TODO 交换两个integer的值
     private static void swap ( Integer integer1 , Integer integer2 ) {
        
    }
}

二:我们刚开始想到的肯定是依赖第三方变量,因为integer是包装类(原以为他传递的是引用)
// TODO 交换两个integer的值
private static void swap ( Integer integer1 , Integer integer2 ) {
    Integer temp = integer1 ;
    integer1 = integer2 ;
    integer2 = temp ;
}
结果为:妈耶没变这怎么搞
before swap: a=1,b=2
after swap: a=1,b=2


三:java中两种传值模式:    ①引用传递    ②值传递    不过这两种传递的都是副本

integer类是final不允许有子类,且在创建对象的时候要不新建要不就在缓存中拿,并且value的字段是私有也没有提供getter方法

可以使用javap来查看到底调用的class中的哪种方法
public class Test{
    public static void main(String[] args){
        Integer a = 1;
        int b = a;
    }
}

PS C:\Users\xxx\Desktop> javap -c Test
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       4: astore_1
       5: aload_1
       6: invokevirtual #3                  // Method java/lang/Integer.intValue:()I
       9: istore_2
      10: return
}

可知自动装箱调用的是valueOf方法,而自动拆箱调用的是intValue方法(该方法类似于get方法)
public int intValue () {
     return value ;
}

四:于是我们使用反射来解决这个问题
// TODO 交换两个integer的值
private static void swap ( Integer integer1 , Integer integer2 ) {
    try {
         Field valueField = Integer . class . getDeclaredField ( "value" );
         valueField . setAccessible ( true );
         int temp = integer1 . intValue ();
         valueField . set ( integer1 , integer2 );
         valueField . set ( integer2 , temp );
        } catch ( Exception e ) {
             // TODO Auto-generated catch block
             e . printStackTrace ();
        }
}
before swap: a=1,b=2
after swap: a=2,b=2

因为对象都是公用的一份字节码文件,value变为可变的之后,即内存中Integer对象会都变为value可变,包括在IntegerCache.cache[]中的缓存都会改变
于是
0.int temp = 1;
1.integer1中的value变为2(IntegerCache.cache[131]),即IntegerCache.cache[130]变为2;
2.integer2中的value调用set的时候,会先把1转为Integer(IntegerCache.cache[130])的再取得他的intValue()值,则还是2;


UnsafeQualifiedIntegerFieldAccessorImpl.class

五:解决方法
〇:只要不在缓存池里就不存在这个问题
①:再新new一个1的Integer
int temp = integer1 . intValue ();
valueField . set ( integer1 , integer2 );
valueField . set ( integer2 , new Integer ( temp ));
②:使用指定的方法setInt()
int temp = integer1 . intValue ();
valueField . set ( integer1 , integer2 );
valueField . setInt ( integer2 , temp );
③:从一位大哥那里学到的(最终解法) 
// TODO 交换两个integer的值
private static void swap ( Integer integer1 , Integer integer2 ) {
    System . out . println ( "after swap: a=2,b=1" );
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值