搞懂java参数传递

本文详细介绍了程序设计中的值传递和引用传递概念,以Java为例,区分了基本类型和引用类型在传递过程中的行为差异。值传递中,对基本类型和不可变引用的修改不影响原始值,而对于可变引用,方法内的修改会反映到原始对象。
摘要由CSDN通过智能技术生成

很多程序设计语言(比如 C++、 Pascal )提供了两种参数传递的方式,值传递和引用传递
在正式介绍这两种类型之前,先说明下实参和形参的概念。

一、实参和形参

  • 实参(实际参数,Arguments):用于传递给函数/方法的参数,必须有确定的值。
  • 形参(形式参数,Parameters):用于定义函数/方法,接收实参,不需要有确定的值。
public class CountOnesInBinary {
    //num为形参
    public static int countOnesInBinary(int num) {
        if (num == 0) {
            return 0;
        } else {
            return num % 2 + countOnesInBinary(num / 2);
        }
    }

    public static void main(String[] args) {
        int num = 23;
        //num为实参
        int result = countOnesInBinary(num);
        System.out.println("数字 " + num + " 的二进制格式中1的个数为: " + result);
    }
}

二、值传递和引用传递

一般的程序设计语言提供了两种参数传递方式

  • 值传递:方法接收的是实参值的拷贝,会创建副本。
  • 引用传递方法接收的直接是实参所引用的对象在堆中的地址,不会创建副本,对形参的修改将影响到实参。

在java中只有值传递,基本数据类型传递的是值的副本,引用数据类型传递的是引用的副本。

  • 对于基本数据类型(如int、double等),传递的是该数据值的一个副本,方法内对这些参数的修改不会影响到原始数据。
  • 对于引用数据类型(如对象、数组等),传递的是引用变量(内存地址)的一个副本。虽然这有时被误解为“引用传递”,但实际上,由于传递的是引用的拷贝,所以它仍然遵循值传递的原则。这意味着在方法内部,你可以通过这个引用拷贝来修改所指向对象的内容,从而影响到原始对象,但是你不能改变引用本身让它指向另一个对象

三、基本类型值传递代码示例

java的基本数据类型包括:

  • 整型:byte, short, int, long
  • 浮点型:float, double
  • 字符型:char
  • 布尔型:boolean

这里以int基本类型举例

package com.datastructures;

public class PrimitiveTypeExample {
    public static void main(String[] args) {
        int originalValue = 10;
        System.out.println("调用前原始值: " + originalValue);
        modifyPrimitive(originalValue);
        System.out.println("调用后原始值: " + originalValue); // 值不变,依旧为10
    }

    static void modifyPrimitive(int value) {
        value = 20; // 修改的是副本的值
        System.out.println("方法内修改后的值: " + value);
    }
}

在这里插入图片描述
可以看到基本类型值传递给方法后,在方法内部改变基本类型的值,不会影响到原始值

四、引用数据类型值传递

引用数据类型包括所有非基本类型的对象,如数组、类实例、接口实例等。

对于某些不可变的引用类型如Integer、String等,传递引用的副本到方法的形参上后,方法内部对引用副本指向的对象做操作,均不会影响原始引用。

代码示例如下:

package com.datastructures;

public class IntegerReferenceExample {
    public static void main(String[] args) {
        Integer originalInteger = 100; // 自动装箱
        System.out.println("调用前Integer值: " + originalInteger);
        modifyIntegerWrapper(originalInteger);
        System.out.println("调用后Integer值: " + originalInteger); // 值保持不变,因为Integer是不可变的
        System.out.println();
        String s = "hello";
        System.out.println("调用前String内容: "+s);
        modifyString(s);
        System.out.println("调用后String内容: "+s);

    }

    static void modifyIntegerWrapper(Integer num) {
        num = 200; // 这里改变了num的引用,让它指向一个新的Integer对象,不影响原对象
        System.out.println("方法内修改后的Integer值: " + num);
    }

    static void modifyString(String s) {
        s = "world";
        System.out.println("方法内修改后的String值: " + s);
    }
}

在这里插入图片描述
执行结果可以看出不可变引传递给方法后,方法内部无论是把引用重新指向新对象,还是对引用本身指向的对象做操作,均不会对原始对象造成改变

对于某些可变的引用类型,比如List或者我们自定义的类实例对象,传递给方法的是原引用的副本,原引用和副本引用指向的对象相同,可以使用副本引用对对象本身做修改操作,但是方法内部如果直接把引用指向新的对象,原始对象仍然不会改变

下面的代码展示了这个特性:

package com.datastructures;

import java.util.List;

public class ReferenceTypeExample {
    public static void main(String[] args) {
        Integer[] originalArray = {1, 2, 3};
        System.out.println("调用前数组内容: " + java.util.Arrays.toString(originalArray));
        modifyArray(originalArray);
        System.out.println("调用后数组内容: " + java.util.Arrays.toString(originalArray)); // 数组内容被修改

        System.out.println("--------------------------------------------------------------------------------");

        List<String> list = java.util.Arrays.asList("a", "b", "c");
        System.out.println("调用前List内容: " + list);
        modifyList(list);
        System.out.println("调用后List内容: " + list);
    }

    static void modifyArray(Integer[] array) {
        array[0] = 100; // 通过引用修改了原始数组的第一个元素
        System.out.println("方法内修改后的数组内容: " + java.util.Arrays.toString(array));
    }

    static void modifyList(List<String> list){
        list = java.util.Arrays.asList("x", "y", "z");
        System.out.println("方法内修改后的List内容: " + list);
    }
}

在这里插入图片描述
从执行结果可以看到,对于可变的引用类型,传递给方法后,对副本引用对象本身做修改操作,会影响原始对象,而把副本引用重新指向新的对象时,不会改变原始对象。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值