Java的值传递

本文探讨了Java中参数传递的两种方式——值传递和引用传递。通过示例代码展示了值传递如何保持原始变量不变,而引用传递如何允许方法内部修改变量。在Java中,所有参数都是按值传递,即使是对象也是传递对象引用的副本,而非实际对象。因此,swap方法无法实现对象的交换,而swap1方法通过临时存储实现了对象属性的交换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、值传递和引用传递

        在程序设计语言中将参数传给方法或函数的方式目前有两种:一种是值传递,一种是引用传递。

        值传递表示将实参的值传递给方法;引用传递表将实参a的地址引用传递给方法。

        Java是采用值传递的,Java程序中的方法得到的总是实参值的拷贝,

 二、代码运行

        我们来看下下面代码的运行结果

public class Main {
    public static void main(String[] args) {
        SingleInstance instance = SingleInstance.getInstance();
        Student a = new Student();
        Student b = new Student();
        a.setName("zhangsan");
        b.setName("lisi");
        System.out.println(a);
        System.out.println(b);
        swap1(a,b);
        System.out.println(a);
        System.out.println(b);
        swap(a,b);
        System.out.println(a);
        System.out.println(b);
    }

    private static void swap1(Student e, Student f) {
        String name = e.getName();
        e.setName(f.getName());
        f.setName(name);
    }

    private static void swap(Student e, Student f) {
        Student a= e;
        e=f;
        f=a;
    }

 
}

结果为

Student{name='zhangsan'}
Student{name='lisi'}
Student{name='lisi'}
Student{name='zhangsan'}
Student{name='lisi'}
Student{name='zhangsan'}

从结果我们可以看出执行swap1方法的进行了交换,这是因为a,b指向的地址没有改变,改变的是指向地址所指向的name发生了改变

而swap方法执行时,创建了a' 和 b',虽然它们的值或地址确实发生了改变,但是方法执行完后,a'、b'出栈,没有影响到a,b,所以没有交换

swap1方法执行前 

swap1 方法执行中

 

swap1方法执行后

然后是swap方法执行前

 

 swap方法执行中

swap方法执行后

 

 所fang

我们再看一组例子

public class Main {
    public static void main(String[] args) {
        int c =10;
        int d=20;
        Integer e =10;
        Integer f=20;
        swap(c,d);
        System.out.println(c);
        System.out.println(d);
        swap(e,f);
        System.out.println(e);
        System.out.println(f);
    }


    private static void swap(int a, int b) {
        int c =a;
        a=b;
        b=c;
    }
    private static void swap(Integer a, Integer b) {
        Integer c =a;
        a=b;
        b=c;
    }
}

 结果为:


10
20
10
20

我们发现其c,d;e,f并没有因为方法而改变;这是因为无论是基本类型还是封装好的Integer类型,都没有改变实际上的值。

方法执行时,栈里放入了10,20,也确实进行了交换;但方法执行完毕时也进行了出栈,但c和d没有进行过交换

 方法执行前

 

方法执行中

 

方法执行完

 

 

### Java值传递与引用递的区别及实现机制 #### 一、概念区分 在讨论Java中的参数递时,重要的是要明白Java采用统一的方式——按值调用(call by value)[^1]。这意味着无论何时向方法递参数,实际上递给该方法的都是原始数据类型的副本或者是对象引用的一个复制。 对于基本数据类型而言,当作为实参给形参的时候,会创建一个新的变量来保存这个数值;而对于引用类型,则是将指向堆内存中某个位置的对象地址复制一份交给函数内部使用[^2]。 #### 二、具体表现形式 - **基本数据类型** 当把一个基础数据类型(比如int, float等)当作参数递给另一个方法时,实际上是在栈桢(stack frame)里创建了一个新的局部变量并赋予其相同的初始值。因此,在被调用的方法内对该参数所做的任何修改都不会影响到原变量的内容。 ```java public static void changeValue(int num){ num = 10; } int a = 5; changeValue(a); System.out.println(a); // 输出仍然是5 ``` - **引用数据类型** 对于像数组或自定义类这样的复杂结构体来说,情况稍微有些不同。虽然也是按照值来进行递,但是这里所说的“值”,指的是对这些实体所持有的引用而非实体本身。换句话说,就是两个不同的地方持有同一个物体的位置信息。所以如果在一个方法体内改变了由这个引用指向的数据成员,则这种变化也会反映在外面可见的状态上。 不过要注意一点,即使可以改变对象状态,也无法让外部指针重新指向其他实例。因为递过来的只是原有引用的一份拷贝而已。 ```java class Person { String name; Person(String n) { this.name = n; } @Override public String toString() { return "Person{name='" + name + "'}"; } } public static void modifyObject(Person p) { p.name = "John"; } // 测试代码如下: Person person = new Person("Alice"); modifyObject(person); System.out.println(person.toString()); // 结果为:Person{name='John'} ``` #### 三、深浅拷贝介绍 为了更好地理解和处理涉及可变对象的情况,还需要掌握关于深拷贝(deep copy) 和 浅拷贝(shallow copy)的知识点: - **浅拷贝**是指只复制最外层容器内的元素而不深入到底部层次去逐级构建新对象的过程。简单来讲就是在不破坏原来关系的前提下建立了一套平行映射表单。这样做可能会导致多个看似独立却共享某些部分资源的现象发生。 - **深拷贝**则是完全重建整个树状图谱下的每一个节点直至叶端为止的操作模式。它能够确保源目标之间没有任何关联性存在从而达到真正意义上的隔离效果。 由于Java默认提供的是浅拷贝功能,所以在需要执行深层次克隆操作之前应当先确认当前环境是否支持序列化接口(Serializable),然后再考虑利用第三方库或者手动编码的方式来完成这项任务[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

herrybody

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值