JAVA如何使用函数进行值交换

文章比较了C++和Java中参数传递的区别,C++支持引用传递和指针交换,而Java只有值传递,对象内部地址值的变化解释了看似能修改对象的原因。讨论了通过Integer交换值的限制以及在Java中实现类似C++交换的策略。

熟悉C/C++的朋友一定知道参数传递大致有值传递,引用传递,指针的方式也可以看做是值传递

因此在C/C++中,想要交换两个参数的值我们可以使用引用传递,或者直接使用指针,就可以实现

例如:

void swap1(int& a,int& b){
    int temp=a;
    a=b;
    b=temp;
}//引用传递


void swap2(int* a,int* b){
    int temp=*a;
    *a=*b;
    *b=temp;
}//使用指针

但是在java当中,只存在值传递这就导致了如下的写法是失败的,因为值传递,函数中只保留实参的副本,不会导致原来的参数的值发生变化

public void swap(int a,int b){
    int temp=a;
    a=b;
    b=temp;
}//交换失败

但是有时候我们又会发现,java中是可以导致值的改变的,例如:

class Test{
    int a;

    public Test() {
    }

    public Test(int a) {
        this.a = a;
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "Test{" +
                "a=" + a +
                '}';
    }
}
public class Main {
    public static void main(String[] args) {
        Test a=new Test(6);
        Test b=new Test(7);
        change(a);
        System.out.println(a);
    }
    public static void change(Test a){
        a.setA(59);
    }
}

这是为什么呢?

java中虽然是值传递,但是java的对象内部保存的值其实是地址值,我们知道java中通过new创建的对象是保存在堆空间中,堆空间中的变量不会随着函数的结束而销毁,因此,虽然进行的是值传递,但是依然可以修改对象的值。

我们可能联想到,既然对象保存的是地址,那么不用int,改用包装类型Interger可不可以实现交换呢?

很遗憾,依然不能这样交换,原因是:

翻看Integer源代码可以发现

    /**
     * The value of the {@code Integer}.
     *
     * @serial
     */
    private final int value;

Integer中保存的值是value这个常量,也就是说不能修改Integer内部保存的值

然而我们实际应用过程中好像是可以修改的,原因如下:

void test(){
    Integer a=6;
    a=100;//a的值变为了100,但是本质不是修改a的值,而是新建了一个Integer,把这个新变量的值赋给了a
}

综上,我们也不能通过Integer实现数值的交换,那么如何实现像C/C++那样的数值交换呢?

大概只有通过封装自己的类,然后通过get,set方法才能实现了。

Java 中,由于函数传递过程只能传不能传址,直接交换基本数据类型变量的无法实现预期效果,不过可以通过一些特定方式来实现交换。 ### 采用对象方式交换 以下是采用对象方式交换两个变量的具体过程: ```java public class Arithmetic { private int x; private int y; public static void main(String[] args) { Arithmetic t = new Arithmetic(); t.x = 4; t.y = 5; System.out.println("交换之前a:" + t.x + " 交换之前b:" + t.y); t.swap(t); System.out.println("交换之后a:" + t.x + " 交换之后b:" + t.y); } public static void swap(Arithmetic t) { int temp; temp = t.x; t.x = t.y; t.y = temp; } } ``` 在这个过程中,首先创建了 `Arithmetic` 类的对象 `t`,并对对象的属性 `x` 和 `y` 进行赋。然后调用 `swap` 方法,将对象 `t` 作为参数传递进去。在 `swap` 方法内部,使用临时变量 `temp` 存储 `t.x` 的,接着将 `t.y` 的赋给 `t.x`,最后将临时变量 `temp`(即原来 `t.x` 的)赋给 `t.y`,从而实现了对象属性交换 [^1]。 ### 采用数组方式交换 以下是使用数组方式交换两个的具体过程: ```java public class Hello { public static void main(String args[]) { int a[] = { 32, 3, 2, 5, 6, 8, 4 }; for (int i = 0; i < a.length; i++) { for (int j = i + 1; j < a.length; j++) { if (a[j] < a[i]) swap(a, i, j); } } for (int i = 0; i < a.length; i++) { System.out.println(a[i]); } } public static void swap(int[] data, int a, int b) { int t = data[a]; data[a] = data[b]; data[b] = t; } } ``` 在这个过程中,定义了一个整型数组 `a`。在两层嵌套的 `for` 循环中,当满足 `a[j] < a[i]` 的条件时,调用 `swap` 方法。`swap` 方法接收数组 `data` 以及两个索引 `a` 和 `b` 作为参数。在 `swap` 方法内部,使用临时变量 `t` 存储 `data[a]` 的,然后将 `data[b]` 的赋给 `data[a]`,最后将临时变量 `t`(即原来 `data[a]` 的)赋给 `data[b]`,实现了数组中两个元素交换 [^4]。 ### 采用包装类方式交换 对于普通的类型,像 `int` 或者 `double` 这样的可以改传它们的包装类 `Integer` 和 `Double`。不过需要注意的是,`Integer` 和 `Double` 是不可变类,不能直接像基本数据类型那样交换,但可以通过自定义类来包装它们实现交换。以下是一个简单示例: ```java class Wrapper { Integer value; Wrapper(Integer value) { this.value = value; } } public class SwapWrapper { public static void main(String[] args) { Wrapper num1 = new Wrapper(10); Wrapper num2 = new Wrapper(20); System.out.println("交换前 num1: " + num1.value + ", num2: " + num2.value); swap(num1, num2); System.out.println("交换后 num1: " + num1.value + ", num2: " + num2.value); } public static void swap(Wrapper a, Wrapper b) { Integer temp = a.value; a.value = b.value; b.value = temp; } } ``` 在这个过程中,首先创建了 `Wrapper` 类,该类包含一个 `Integer` 类型的属性 `value`。在 `main` 方法中创建了两个 `Wrapper` 对象 `num1` 和 `num2` 并进行赋。然后调用 `swap` 方法,将这两个对象作为参数传递进去。在 `swap` 方法内部,使用临时变量 `temp` 存储 `a.value` 的,接着将 `b.value` 的赋给 `a.value`,最后将临时变量 `temp`(即原来 `a.value` 的)赋给 `b.value`,实现了包装类对象属性交换
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值