Java 值传递,引用传递,方法参数传递

写在前面

1、本文解决的问题:Java是按照值传递还是引用传递?

2、写作背景:QT项目刚刚结束,开发过程中被 C++ 的引用传递教育了好几回,同时,作为一名热爱Java领域的“打工人”,Java中方法参数的传递是怎样的呢?

3、写作心情:涕笑三声

预备知识

1、什么是形参和实参?

形参: 形式参数,用于定义方法的时候使用的参数,是用来接收调用者传递的参数的。
实参: 实际参数,用于调用时传递给方法的参数。

例如:

public class Test {
    
    
    public static void main(String[] args) {
    
    
        test("涕笑三声");    //"涕笑三声" 为实参
    }
    public static void test(String s){
    
    
                           //s 为形参
    }
}

2、什么是值传递和引用传递(也可以说是值调用和引用调用)?

值传递: 是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对 参数进行修改,将不会影响到实际参数。
引用传递: 是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

3、掌握Java基础知识。

证明

在Java中只有两种类型的参数传递:基本数据类型和引用数据类型。

所以,只有确定这两种类型的传递方式,才能确定Java方法参数传递的方式。

扫描二维码关注公众号,回复: 13120093 查看本文章

定义: 可以确定的是,Java 是按照值传递。
定理: 值传递和引用传递的定义与特征。


下面为Java是按照值传递的求证过程:


  • 证明1:假设基本数据类型(即数值型和布尔型)是按照值传递

向方法传递一个基本类型的参数值,然后在方法中对参数值加1,观察方法调用前的值是否发生变化。

代码如下:

public class Test {
    
    
    public static void main(String[] args) {
    
    
            int n = 1;
            System.out.println("调用前原数值:" + n);
            basicTypeTest(n);
            System.out.println("调用后原数值:" + n);
        }
        public static void basicTypeTest(int n){
    
    
            n = n+1;
            System.out.println("方法中改变后:" + n);
        }
}

运行结果:

调用前原数值:1
方法中改变后:2
调用后原数值:1

可以看到,主函数中的数值没有发生变化。

所以求证1为真。


拷贝过程如下图:
在这里插入图片描述

求证1结论:
1、基本数据类型是按照值传递
2、一个方法不可能修改一个基本数据类型的参数。
3、方法接收的是数值的一个拷贝。


  • 证明2:假设引用数据类型是按照值传递

向方法传递一个引用数据类型参数,修改对象参数状态,观察方法调用前所对应的值是否发生变化。

代码如下:

public class Test {
    
    
    public static void main(String[] args) {
    
    
    	//创建一个实例
        ReferenceTypeTest refer = new ReferenceTypeTest("我是张三");
        //打印对象名字
        System.out.println("调用前名字:" + refer.getName());
        //修改对象名字
        updateName(refer);
        //修改后打印对象名字
        System.out.println("调用后名字:" + refer.getName());
    }
    //修改参数方法
    public static void updateName(ReferenceTypeTest refer){
    
    
        refer.setName("涕笑三声");
        System.out.println("方法中改变后:" + refer.getName());
    }
}
class ReferenceTypeTest{
    
    
    private String name;
    public ReferenceTypeTest(String name){
    
    
        this.name = name;
    }
    public String getName(){
    
    
        return this.name;
    }
    public void setName(String name){
    
    
        this.name = name;
    }
}

运行结果:

调用前名字:我是张三
方法中改变后:涕笑三声
调用后名字:涕笑三声

可以看到,主函数中的数值发生了变化。

参考基本类型的传递的逻辑,这里好像可以判定引用数据类型的传递是按照是引用传递的方式。

但有一个问题!!!

引用传递有一个重要特征:传递的是值的引用,也就是说传递前和传递后都指向同一个引用。 这里只能证明引用数据类型的传递可以改变堆中的值,无法判断传递前后是否为同一个引用。

所以,如果传递前后是同一个引用,则求证2不成立


  • 再次求证:假设传递前后为同一个引用

向方法传递两个引用数据类型参数,然后在方法中交换两个参数引用,观察方法调用前的两个对象引用是否交换

代码如下:

public class Test {
    
    
    public static void main(String[] args) {
    
    
    	//创建实例 refer1
        ReferenceTypeTest refer1 = new ReferenceTypeTest("我是张三");
        //创建实例 refer2
        ReferenceTypeTest refer2 = new ReferenceTypeTest("涕笑三声");
        //打印 refer1,refer2 的名字
        System.out.println("调用前名字 refer1:" + refer1.getName() + "\t" + "refer2:" + refer2.getName());
        //把引用传递到方法中,方法中接收的引用进行交换
        changeReference(refer1,refer2);
        //方法执行后打印 refer1 ,refer2 的名字
        System.out.println("调用后名字 refer1:" + refer1.getName() + "\t" + "refer2:" + refer2.getName());
    }
    //交换引用方法
    public static void changeReference(ReferenceTypeTest refer1,ReferenceTypeTest refer2){
    
    
        ReferenceTypeTest temp = refer1;
        refer1 = refer2;
        refer2 = temp;
        System.out.println("方法中交换后 refer1:" + refer1.getName() + "\t" + "refer2:" + refer2.getName());
    }
}
class ReferenceTypeTest{
    
    
    private String name;
    public ReferenceTypeTest(String name){
    
    
        this.name = name;
    }
    public String getName(){
    
    
        return this.name;
    }
    public void setName(String name){
    
    
        this.name = name;
    }
}

运行结果:

调用前名字 refer1:我是张三	refer2:涕笑三声
方法中交换后 refer1:涕笑三声	refer2:我是张三
调用后名字 refer1:我是张三	refer2:涕笑三声

可以看到,方法参数引用交换,并没有影响到原对象引用。而 传递后的引用是原引用的拷贝(地址值)

所以,引用传递前后不是一个引用,再次求证不成立,求证2为成立。


求证2对象参数修改过程如下图:
在这里插入图片描述
再次求证 引用交换过程如下图:
在这里插入图片描述

证明2结论:
1、引用数据类型按照值传递
2、一个方法可以可以修改对象参数的状态
3、方法接收的是一个引用地址(地址值)的拷贝


结论

1、Java 程序设计语言总是采用按值传递。

2、一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)

3、一个方法可以改变一个对象参数的状态。

4、一个方法不能让对象参数引用一个新的对象。


从代码逻辑上来看

if("求证1" && "求证2"){
    
    
	System.out.println("Java 程序设计语言总是采用按值传递。")
}else{
    
    
    System.out.println("并非Java语言");
}


——THE END——

最后,在新的一年,祝各位道友身体健康,万事如意。

猜你喜欢

转载自blog.csdn.net/weixin_46022868/article/details/112062473