java方法调用时的参数传递问题

本文深入探讨Java中的参数传递机制,区分基本数据类型与引用数据类型的传递方式,并通过实例代码展示如何影响方法内外的变量。

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

OOP编程中会涉及到方法调用的参数传递问题。之前一直没搞明白“值传递”与“引用传递”,在网上找了些资料,发现也说的模糊不清。经过小弟一整天时间的研究发现,以调用方法时传递参数的是变量为前提,那么参数传递都是拷贝传递。下面分为两中类型来说:基本数据类型和引用数据类型。

一,基本数据类型

基本数据类型赋值给变量后,变量存储的就是变量的具体值;当调用一个方法需要传递该基本数据类型变量时,java是将该变量的具体内容拷贝传递给方法。在被调用的方法中拿到的变量只是原来具体值的副本,所以在被调用方法中操作局部变量并不会影响调用方法中的变量的内容(注意:拷贝传递)

代码如下:

public class Test{

    static void function(int x){
        x = 10;
    }

    public static void main(String[] args) {
        System.out.println("Hello World!");
        int x = 5;
        function(x);
        System.out.println("x = " + x);//运行结果
    }
}

// 运行结果
Hello World!
x = 5

二,引用数据类型

引用数据类型赋值给变量后,变量中存储的是什么呢?与基本数据类型不同的是,引用数据类型变量存储的是对象的引用(地址值,指针)。由于java中方法参数的传递是拷贝传递,那么被调用的方法的形参接收到的就是引用的拷贝。也就是说此时有多个变量指向同一个对象。当然在被调用的方法体中操作对象是会影响到调用者中的对象的,因为两者是指向同一个对象。这里有一个问题,如果可以理解的话,那么参数传递的问题就不会再困扰你了。请看代码:

public class Main {

    static void function(Tank tank){
        tank = null;
    }

    public static void main(String[] args) {
        System.out.println("Hello World!");
        Tank tank = new Tank(5);
        System.out.println("原来tank.x = " + tank.x);
        function(tank);
        System.out.println("变换后tank.x = " + tank.x);
    }
}

class Tank {
    int x;

    public Tank(){}

    public Tank(int x){
        this.x = x;
    }
}

//运行结果
Hello World!
原来tank.x = 5
变换后tank.x = 5
为什么没有报NullPointerExceotion呢?不是说引用数据类型的传递会影响原来的值吗?其实,这里需要注意的关键问题就是拷贝传递,function()的形参接收到的是传过来的地址值,但是原方法中的tank也还存储着这个对象的地址值啊。执行tank = null;只是将形参的地址值置为null。再看下面一段代码:

public class Main {

    static void function(Tank tank){
        tank.x = 10;
    }

    public static void main(String[] args) {
        System.out.println("Hello World!");
        Tank tank = new Tank(5);
        System.out.println("原来tank.x = " + tank.x);
        function(tank);
        System.out.println("变换后tank.x = " + tank.x);
    }
}

class Tank {
    int x;

    public Tank(){}

    public Tank(int x){
        this.x = x;
    }
}
// 运行结果
Hello World!
原来tank.x = 5
变换后tank.x = 10
果然值变了。你想啊,由于是拷贝传递,在function()中的tank变量也是指向原来的那个对象,那么这里的一顿操作势必会改变对象的内容。ok,就到这里!

### Java 方法调用参数传递机制详解 Java 中的方法调用涉及两种主要的参数传递方式:按值传递(Pass by Value)和按引用传递(Pass by Reference)。然而,在 Java 的设计哲学中,所有的参数都是通过 **值传递** 实现的。即使是对象类型的参数也不例外。 #### 值传递的概念 当一个基本数据类型(如 `int`、`double` 等)被作为参数传递方法,实际上传递方法的是该变量的一个副本[^1]。因此,任何对这个副本所做的修改都不会影响原始变量的值。例如: ```java public class PassByValueExample { public static void changePrimitive(int value) { value = 10; } public static void main(String[] args) { int num = 5; changePrimitive(num); System.out.println("After method call: " + num); // 输出仍然是 5 } } ``` 在这个例子中,尽管在 `changePrimitive` 方法内部改变了 `value` 的值,但主程序中的 `num` 并未受到影响[^4]。 --- #### 对象的值传递 对于对象类型的参数,情况略有不同。虽然 Java 使用的是值传递,但在这种情况下,“值”指的是对象的引用地址而不是对象本身。这意味着如果在一个方法中更改了对象的状态(比如修改其字段),这些变化会反映回原对象。但是,如果尝试重新分配一个新的对象给参数,则不会影响外部的对象实例。例如: ```java class Person { String name; public Person(String name) { this.name = name; } } public class PassObjectReference { public static void modifyPerson(Person person) { person.name = "John"; // 修改对象状态 } public static void reassignPerson(Person person) { person = new Person("Doe"); // 尝试重置引用 } public static void main(String[] args) { Person p = new Person("Alice"); modifyPerson(p); System.out.println("Name after modification: " + p.name); // John reassignPerson(p); System.out.println("Name after reassignment: " + p.name); // 仍然为 John } } ``` 这里的关键在于理解 `person` 是指向堆内存中某个位置的引用。即使我们可以在方法内操作它所指代的内容,也无法改变它的指向目标[^4]。 --- #### 方法递归调用参数传递的关系 除了普通的函数调用外,递归也是一种重要的编程技术。每次进入新的递归层,都会创建一组全新的局部变量拷贝[^2]。这进一步验证了无论是在常规还是递归场景下,Java 都严格遵循着基于值复制的原则来进行参数交换。 考虑下面的例子展示了如何利用栈帧保存每一轮迭代的信息直到满足终止条件为止: ```java public class RecursiveParameterTest { public static void recursiveMethod(int level){ if(level<=0){ return ; } System.out.println("Current Level:"+(level--)); recursiveMethod(level); } public static void main(String []args){ recursiveMethod(3); } } ``` 每当 `recursiveMethod()` 被再次调用候,当前级别的数值会被压入系统调用栈之中形成独立的一份记录直至达到基础情形才逐一释放并返回上级呼叫者那里继续执行剩余部分逻辑[^2]. --- ### 总结 综上所述,无论是基本数据类型还是复杂的数据结构,在 Java 编程语言里都采用统一的方式——即按照值来完成参数之间的交互行为。即便是看似涉及到所谓“引用”的场合也不过是对底层存储单元地址进行了相应的转移而已,并不意味着真正意义上的直接操纵源实体自身属性或者链接关系的变化[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值