交换两个变量的误区(java)

在java中参数的传递有两种方式,传值和引用,实际上引用也是传的值。当在一个方法中要交换两个参数对应的值时,可能会有一系列问题。如下:

package com.xx;

import java.lang.reflect.Field;

public class Test01 {
    public static void main(String[] args) {
        Integer a = 1, b = 2;
        swap(a, b);
        System.out.println("a=" + a + "; b=" + b);
    }

    /**
     * 交换变量a和b的值
     * 
     * @param a
     * @param b
     */
    private static void swap(Integer a, Integer b) {
            int tmp = a.intValue();
            a = b;
            b = tmp;
    }

    private static void swap1(Integer a, Integer b) {
        try {
            Field field = Integer.class.getDeclaredField("value");
            field.setAccessible(true);//(1)
            int tmp = a.intValue();//(2)
            field.set(a, b.intValue());//(3)
            System.out.println("tmp:" + tmp + "; valueOf:" + Integer.valueOf(tmp));//tmp:1; valueOf:2
            System.out.println("a:" + a);//a:2
            field.set(b, tmp);//(4-1)
            //field.set(b, new Integer(tmp));//(4-2)
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}  

在swap(q,b)方法中直接交换后结果是没有变化,因为此方法中的两个变量都是局部变量,方法运行完后变量失效,所有此种方式不行。

实例中的Integer是一个包装类,而真正存储值的是“private final int value;”,value是一个私有的变量,如果改变一个私有变量的值,可以使用反射。

(1):使用Field设置私有方法前,必须设置为可执行的

(2):此时tmp值为1,tmp指向的就是value的内存地址,即a的实际的值的内存地址

(3):set方法设置的是两个Object对象,先将b.intValue()转为包装类(Integer.valueOf(xx))再设置,b的值在缓存池中存在。此时a的值为2,即a中value指向的内存值也为2,也就是说tmp此时指向的内存地址的值为2

(4-1):此时如果直接将tmp的值设置到b中,那么将tmp转换为包装类后的值为2(a.valueOf(tmp),缓存中存在,并且上一步已将缓存中的值修改)

(4-2):重新实例化一个对象,而不是从缓存池中获取

在Integer中,有一个缓存池(-128 到 127),调用valueOf前会先判断是否命中缓存池

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值