商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 【Java】Java中的swap

【Java】Java中的swap

  发布于2026-07-16 阅读(0)

扫一扫,手机访问

Ja va中的swap


文章目录

本文先回顾C/C++的swap方式,再探讨Ja va中为何无法直接实现,最后通过反射给出一个取巧方案。

C/C++中的swap

说起交换两个变量的值,C语言的老手马上会想到指针——传个地址进去,把两个内存位置的值一调换,干净利落。代码长这样:

void swap(int *a, int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

C++就更灵活了,指针和引用任选:

void swap1(int *a, int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
void swap2(int &a, int &b){
    int temp;
    temp = a;
    a = b;
    b = temp;
}

跑个测试看看,结果自然是如愿以偿:

这里写图片描述

原理很简单:函数拿到的是变量在内存中的真实地址(或者引用,本质也是地址的别名),对地址所指向的内容做修改,外面跟着变。可一旦切换到Ja va,情况就彻底不一样了。

Ja va中的swap

Ja va不像C/C++那样暴露指针给你玩。基本类型(int、double、float等等)传参的时候统统是值传递——函数里拿到的是原始值的一个副本。你在函数里把副本换来换去,外面的变量纹丝不动。效果就像这样:

这里写图片描述

那对象类型呢?Ja va里对象传的是“引用”,但这个引用和C++的引用不是一回事。Ja va的值拷贝传递的是引用的副本——说白了,是两个指向同一对象的遥控器。你可以通过其中一个遥控器修改对象的内部状态,但如果试图把遥控器本身(引用)重新指向别的对象,那改的只是函数内部那个副本,外面的遥控器依然指向原来的对象。所以下面的代码同样达不到交换目的:

这里写图片描述

内存里的实际情况是这样的:两个引用副本交换了指向,但原始引用纹丝不动。

这里写图片描述

那么,Ja va真的没法实现一个像样的swap吗?也不尽然。下面就用反射,对Integer类搞个“偷天换日”:

这里写图片描述

import ja va.lang.reflect.Field;

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

    public static void swap(Integer a, Integer b) {
        if (a == null || b == null) {
            return;
        }
        // 获得a的class对象
        Class integerClass = (Class) a.getClass();
        try {
            // 获得value属性
            Field value = integerClass.getDeclaredField("value");
            // 设置权限为可访问
            value.setAccessible(true);
            // 交换
            int temp = a;
            value.setInt(a, b);
            value.setInt(b, temp);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

注意,这个方案只适用于Integer这类封装了基本类型的对象(而且依赖内部字段“value”)。换成其他自定义对象,只要内部有可修改的字段,道理是一样的。但话说回来,这种写法更多是演示反射的威力,实际工程中压根没必要这样折腾——为了swap绕这么大弯子,不如直接换个思路设计代码。时间宝贵,把精力花在学习真正有意义的东西上吧。

总结

C/C++的swap走的是“传地址、改内存”的路子——指针或引用直接操作变量所在的内存位置。Ja va则对程序员屏蔽了地址概念,为的是减少指针误用带来的风险。

Ja va里所有方法参数传递都是值拷贝:基本类型拷贝值的本体;对象类型拷贝引用的副本。通过这个引用副本可以修改对象内部的值,但无法改变外部实参的引用指向。反射机制可以绕过访问控制,强行修改对象的私有字段,从而在某种程度上实现swap,但代价高、可维护性差,并不推荐在日常代码中使用。

本文转载于:https://blog.csdn.net/cflys/article/details/71102021 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注