java.lang.reflect.Filed.class中setInt与set的区别

先看下面方法:
public static void swap(Integer a , Integer b){
}
要求:交换a、b的值,并可以将交互后的结果返回给调用方。就是说,比如在main方法有种如下调用代码:
Integer a = 400;
Integer b = 200;
System.out.println("a="+a+",b="+b);
swap(a,b);
System.out.println("a="+a+",b="+b);
那么,期望的结果是:
400 ,200
200 ,400

先公布答案。
我们知道,如果将方法内部的局部变量实现交互,很简单。如下3行轻松搞定。
int temp = b;
b=a;
a=temp;
但是,如果要求将交互结果回传出来,就不奏效了。正确的姿势是利用反射,即java.lang.reflect.Filed类。

public static void swap(Integer a , Integer b){
        try {
            Field field = Integer.class.getDeclaredField("value");
            field.setAccessible(true);
            int temp = b;
            field.set(b, a);
            field.set(a,new Integer(temp));

        } catch (Exception e) {
            e.printStackTrace();
        }
}


好。接下来说问题。先看如下实现。

public static void swap(Integer a , Integer b){
        try {
            Field field = Integer.class.getDeclaredField("value");
            field.setAccessible(true);
            int temp = b;
            field.set(b, a);
            field.set(a,temp);

        } catch (Exception e) {
            e.printStackTrace();
        }
}

反复执行程序,发现当实参b>127 && b<-128时,可以正常交换;而一旦b∈[-128,127]时,这种交换并未改变a的值。
将field.set(a,temp);改成field.setInt(a,temp);之后,是可以解决的。
为什么呢?这跟swap方法中的局部变量temp是基本类型int有关,下面进一步阐释。

我们通常利用反射给对象的属性赋值时,都是用set方法。
那么,set与setInt在对于整型数字处理方面,有什么区别呢?
仔细推敲两个方法的的javadoc可以得到结论。

setInt(Object obj, int i)
Sets the value of a field as an int on the specified object. This method is equivalent to set(obj, iObj), where iObj is a Integer object and iObj.intValue() == i.
这个方法等效于set(obj, iObj),在这个set方法第二个参数iObj的类型是Integer,并且((Integer)iObj).intValue()==setInt方法的第二个参数值i的情况下。

set(Object obj, Object value)
Sets the field represented by this Field object on the specified object argument to the specified new value. The new value is automatically unwrapped if the underlying field has a primitive type.

┢1) set方法的value参数是Object,要求用包装类型(wrapped type),不能传基本类型参数(primitive type)。
┢2) setInt的第二个参数是int(即使传的是Integer,也会拆箱为int)。
上面的观点1)并不妥当,比如上面的示例里,b的值在[-128,127]时是不行的,而这个范围外的值是没问题的,我们知道Integer类里的缓存数组cache的取值范围就是[-128,127],不清楚这跟set的这种用法有什么关系。总之,用set方法时,value传包装类型是万无一失的。

原文地址:https://www.cnblogs.com/buguge/p/13914947.html