一道编程题目

版权声明:本文为博主原创文章,未经博主允许不得转载。 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表示需要修改的域的新值来替换原有的值。

猜你喜欢

转载自blog.csdn.net/u012934325/article/details/83013293