java基础—方法的参数传递机制

java基础—方法的参数传递机制

1、基本类型参数传递

  Java里方法的参数传递方式只有一种:值传递。所谓值传递,就是将实际参数值的副本(复制品)传入方法内,而参数本身不会受到任何影响。
  Java里的参数传递类似于《西游记》里的孙悟空,孙悟空复制了一个假孙悟空,这个假孙悟空具有和孙悟空相同的能力,可除妖 或被砍头。但不管这个假孙悟空遇到什么事,真孙悟空不会受到任何影响。与此类似,传入方法的是实际参数值的复制品,不管方法 中对这个复制品如何操作,实际参数值本身不会受到任何影响。下面程序演示了方法参数传递的效果。

    public static void swap(int a, int b) {
        // 下面三行代码实现a、b变量的值交换。
        // 定义一个临时变量来保存a变量的值
        int tmp = a;
        // 把b的值赋给a
        a = b;
        // 把临时变量tmp的值赋给b
        b = tmp;
        System.out.println("swap方法里,a的值是" + a + ";b的值是" + b);
    }

    public static void main(String[] args) {
        int a = 6;
        int b = 9;
        swap(a, b);
        System.out.println("交换结束后,变量a的值是" + a + ";变量b的值是" + b);
    }

运行上面程序,看到如下运行结果:
swap方法里,a的值是9:b的值是6 交换结束后,变量a的值是6;变量b的值是9

  从上面运行结果来看, swap()方法里a和b的值是9、6,交换结束后,变量a和b的值依然是6、9。从这个运行结果可以看出,main()方 法里的变量a和b, 并不是swap()方法里的a和b。 正如前面讲的, swap()方法的a和b只是main()方法里变量a和b的复制品。 下面通过示意图来说明上面程序的执行过程。 Java程序总是从main()方法开始执行, main()方法开始定义了a、b两个局部变量, 两个变量在内存中的存储示意图如下图所示。
在这里插入图片描述

  当程序执行swap()方法时, 系统进入swap()方法, 并将main()方 法中的a、b变量作为参数值传入swap()方法, 传入swap()方法的只是 a、b的副本,而不是a、b本身,进入swap()方法后系统中产生了4个变 量,这4个变量在内存中的存储示意图如下图所示。
在这里插入图片描述
  在main()方法中调用swap()方法时, main()方法还未结束。 因此,系统分别为main()方法和swap()方法分配两块栈区, 用于保存 main()方法和swap()方法的局部变量。 main()方法中的a、b变量作为参数值传入swap()方法, 实际上是在swap()方法栈区中重新产生了两个变量a、b, 并将main()方法栈区中a、b变量的值分别赋给swap()方法栈区中的a、b参数(就是对swap()方法的a、b形参进行了初始化)。此时,系统存在两个a变量、两个b变量,只是存在于不同的方 法栈区中而已。
  程序在swap()方法中交换a、b两个变量的值,实际上是对上图中灰色覆盖区域的a、b变量进行交换,交换结束后swap()方法中输出a、b变量的值,看到a的值为9,b的值为6,此时内存中的存储示意图如下图所示。
在这里插入图片描述
程序改变的只是swap()方法栈区中的a、b。 这就是值 传递的实质:当系统开始执行方法时,系统为形参执行初始化,就是 把实参变量的值赋给方法的形参变量,方法里操作的并不是实际的实 参变量。

2、引用类型参数传递

  前面看到的是基本类型的参数传递, Java对于引用类型的参数传 递,一样采用的是值传递方式。但许多初学者可能对引用类型的参数 传递会产生一些误会。下面程序示范了引用类型的参数传递的效果。

class DataWrap {
    int a;
    int b;
}

public class ReferenceTransferTest {
    public static void swap(DataWrap dw) {
        // 下面三行代码实现dw的a、b两个成员变量的值交换。
        // 定义一个临时变量来保存dw对象的a成员变量的值
        int tmp = dw.a;
        // 把dw对象的b成员变量值赋给a成员变量
        dw.a = dw.b;
        // 把临时变量tmp的值赋给dw对象的b成员变量
        dw.b = tmp;
        System.out.println("swap方法里,a成员变量的值是" + dw.a + ";b成员变量的值是" + dw.b);
        // 把dw直接赋为null,让它不再指向任何有效地址。
        dw = null;
    }

    public static void main(String[] args) {
        DataWrap dw = new DataWrap();
        dw.a = 6;
        dw.b = 9;
        swap(dw);
        System.out.println("交换结束后,a成员变量的值是" + dw.a + ";b成员变量的值是" + dw.b);
    }
}

运行上面程序,看到如下运行结果:
swap方法里,a成员变量的值是9;b成员变量的值是6 交换结束后,a成员变量的值是9:b成员变量的值是6
  从上面运行结果来看, 在swap()方法里, a、b两个成员变量的值 被交换成功。不仅如此,当swap()方法执行结束后,main()方法里a、 b两个成员变量的值也被交换了。这很容易造成一种错觉:调用swap() 方法时, 传入swap()方法的就是dw对象本身, 而不是它的复制品。 但这只是一种错觉,下面还是结合示意图来说明程序的执行过程。
  程 序 从 main() 方 法 开 始 执 行 , main() 方法开始创建了一个DataWrap对象, 并定义了一个dw引用变量来指向DataWrap对象, 这是一个与基本类型不同的地方。创建一个对象时,系统内存中有两个东西:堆内存中保存了对象本身,栈内存中保存了引用该对象的引用变量。 接着程序通过引用来操作DataWrap对象, 把该对象的a、b两个成 员变量分别赋值为6、9。此时系统内存中的存储示意图如下图所示。
在这里插入图片描述
  接下来,main()方法中开始调用swap()方法,main()方法并未结 束, 系统会分别为main()和swap()开辟出两个栈区,用于存放main() 和swap()方法的局部变量。调用swap()方法时,dw变量作为实参传入 swap()方法,同样采用值传递方式:把main()方法里dw变量的值赋给 swap()方法里的dw形参, 从而完成swap()方法的dw形参的初始化。 值 得指出的是,main()方法中的dw是一个引用(也就是一个指针), 它 保存了DataWrap对象的地址值,当把dw的值赋给swap()方法的dw形参 后, 即让swap()方法的dw形参也保存这个地址值,即也会引用到堆内 存中的DataWrap对象。 下图显示了dw传入swap()方法后的存储示意图。
在这里插入图片描述
  从上图来看,这种参数传递方式是不折不扣的值传递方式,系统一样复制了dw的副本传入swap()方法, 但关键在于dw只是一个引用变 量,所以系统复制了dw变量,但并未复制DataWrap对象。
  当程序在swap()方法中操作dw形参时,由于dw只是一个引用变 量,故实际操作的还是堆内存中的DataWrap对象。 此时,不管是操作 main()方法里的dw变量,还是操作swap()方法里的dw参数, 其实都是操作它们所引用的DataWrap对象,它们引用的是同一个对象。因此,当swap()方法中交换dw参数所引用DataWrap对象的a、b两个成员变量 的值后, 可以看到main()方法中dw变量所引用DataWrap对象的a、b两 个成员变量的值也被交换了。
  为了更好地证明main()方法中的dw和swap()方法中的dw是两个变 量,在swap()方法的最后一行增加如下代码:

//把dw直接赋值为nu11,让它不再指向任何有效地址
 dw = nul;

  执行上面代码的结果是swap()方法中的dw变量不再指向任何有效 内存, 程序其他地方不做任何修改。 main()方法调用了swap()方法 后,再次访问dw变量的a、b两个成员变量,依然可以输出9、6。可见 main()方法中的dw变量没有受到任何影响。 实际上, 当swap()方法中 增加dw=null;代码后,内存中的存储示意图如下图所示。
在这里插入图片描述
  从上图来看,把swap()方法中的dw赋值为null后,swap()方法中 失去了DataWrap的引用, 不可再访问堆内存中的DataWraper对象。 但 main()方法中的dw变量不受任何影响, 依然引用DataWrap对象, 所以 依然可以输出DataWrap对象的a、b成员变量的值。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值