一文说明Java为什么只有按值调用

本文探讨了Java中方法参数传递是按值还是按引用的问题。通过示例代码分析,说明Java中参数传递实际上是按值传递,即传递的是对象引用的值,而非对象本身。文中通过Employee对象的交换示例和薪资翻倍的例子,清晰地展示了即使形参变化,实参的引用值并未改变,从而证实Java中没有按引用传递现象。
摘要由CSDN通过智能技术生成

  初学Java不少同学都对方法参数是按值调用还是按引用调用模棱两可,网上帖子也是众说纷纭,部分文章干脆采取中庸之道,认为两者兼而有之,怕是止增笑耳。下面笔者谈谈自己的见解,来证明一下Java为什么只有值调用而没有引用调用。

首先我们重温一下什么是值调用,值调用表示方法接收的是调用者提供的值(注意这个“值”不仅仅是数值);那什么是按引用调用呢?它表示方法接收的是调用者提供的变量地址。说白了调用者和被调用者的地址一样了,这两者就是同一变量了,一个变了另一个一定变,唇亡齿寒的关系,也就是对形参所做的任何改变都会反映在实参上。

有了前期的铺垫我们直接来看代码:

package summer;

public class ParamTest {
    public static void swap (Employee x,Employee y)
    {
        Employee temp=x;
        x=y;
        y=temp;
        System.out.println("完事儿之后x="+x.getName());
        System.out.println("完事儿之后y="+y.getName());
        
    }
    
    public static void main(String[] args)
    {

Employee a=new Employee("liu",200);
        Employee b=new Employee("sun",3000);
        System.out.println("before a="+a.getName());
        System.out.println("before b="+b.getName());
        ParamTest.swap(a,b);
       System.out.println("after a="+a.getName());
        System.out.println("after b="+b.getName());
        }}

大家非常熟悉的交换值函数,public static void swap (Employee x,Employee y)在这一行中,形参x和实参a指向同一对象1;形参y和实参b指向同一对象2。如果Java在按引用调用的话x的地址和a的地址就一样了,也就是x和a是同一变量(虽然形参和实参是一个地址,是同一个变量这在java里本就不可能)  因此x,y在交换完事儿之后,a和b的值也是交换完的。是这样的吗?我们看看结果:

事与愿违,形参x,y完成交换而实参a,b无动于衷。所以按引用传递是站不住脚的,那么笔者所说的按值传递,在这个问题中“值”指的什么呢?拿实参a和形参x来讲,这里传递的值是a的值也就是引用的值,就是(引用)a指向的那个对象的地址!注意是a指向的那个对象的地址,不是引用a自身的地址。a不是对象,它是引用,它的值是对象的地址。它自身也有地址的。

如果说a自身的地址传给x了,那叫按引用调用。事实并非如此。

看到这里读者会问,那这个例子怎么体现的形参的“值”变了,实参的“值”没变呢?且看这两行

           x=y;
        y=temp;

引用之间复制了说明什么?说明new了!说明引用指向的对象变了!我们来看这张图

 

 引用x指向的对象改了,说明x的值改了,改为对象2的地址了。正因为是按值调用,a的值没有发生变化,仍是对象1的地址,a仍指向对象1。至此相信大家已经信服了Java只有按值传递。

下面再举一个易混淆的例子:

package summer;

public class ParamTest {

public static void tripleSalary(Employee y) {
            
            y.raiseSalary(200); //静态方法不能直接调用非静态方法,要通过对象调用(实例化)
            System.out.println("end of method:salary="+y.getSalary());
            }

public static void main(String[] args)
    {Employee harry =new Employee("tao",5000);
    System.out.println("before:salary="+harry.getSalary());
    ParamTest.tripleSalary(harry);
    System.out.println("after:salary="+harry.getSalary());

}}

 

 

 我们观察到这里实参随着形参变了,难道按引用传递了?非也,还是按值传递,这里的值是什么呀?当然还是两个引用所指的那个对象的地址,形参y和实参harry一直还是指向的同一个对象啊,形参方法中有new吗?指向的对象变了吗?所以形参的值变了吗?恐怕都没有吧!

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值