版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012934325/article/details/83013293
昨天在微信群看到有人在讨论一个问题,
具体题目如下:
入参两个Intger,返回空,然后使这个两个值在调用函数后交换。打印交换后的值,比如你初始化两个变量a和b对应的值分别是3,4那么通过调用方法,传入这两个参数,然后再次打印,a和b的值应该就是4和3而不在是3,4.
在Java中我们都知道是值传递,所以刚看到题目时,你可能觉得没有值返回,怎么可以实现?其实我们可以利用反射的思想来进行修改对象的值,最后再打印对象的值。
具体的实现如下:
import java.lang.reflect.Field;
public class SwapTwoNumber {
public static void main(String[] args) {
Integer num1 = 3;
Integer num2 = 4;
System.out.println("交换前:");
System.out.println("num1 = :" + num1 + " ===== " + "num2 = : "+ num2);
swapTwoIntegerNoReturn(num1,num2);
System.out.println("交换后:");
System.out.println("num1 = :" + num1 + " ===== " + "num2 = : "+ num2);
}
/**
* 入参两个Intger,返回空,然后使这个两个值在调用函数后交换
* @param num1
* @param num2
*/
private static void swapTwoIntegerNoReturn(Integer num1, Integer num2) {
try {
//通过反射获取Integer对象中的私有域value
Field field = Integer.class.getDeclaredField("value");
field.setAccessible(true);
int temp = num1.intValue();
//调用set(obj,value)方法,obj表示要修改的对象,value 表示要给修改对象赋予的值
field.set(num1, num2);
field.set(num2, new Integer(temp));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
关于上述代码中我和需要使用value属性和set方法,你可以看看源码。
Integer的源码中有这样一段代码:
/**
* The value of the {@code Integer}.
*
* @serial
*/
private final int value;
此处的私有域value表示的应该是Integer对象的值,所以需要使用value属性。
再看一下package java.lang.reflect.Field类中的set方法:
/**
* Sets the field represented by this {@code 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.
* @param obj the object whose field should be modified
* @param value the new value for the field of {@code obj}
* being modified
*/
@CallerSensitive
public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
}
}
getFieldAccessor(obj).set(obj, value);
}
通过上面的部分源码,我们可以参数来set方法的第一个参数obj代表对象需要修改的域。value表示需要修改的域的新值来替换原有的值。