方法参数按值传递

php中的函数、方法中参数有两种传递方法,按值传递以及按引用地址传递。对于普通变量,php采用按值传递,而对于对象,则默认使用按引用地址传递。

但在java中,方法的参数总是按照值传递的。也就是说,方法得到的是所有参数值的一个副本。若函数中没有使用return将此副本返回给调用者,该副本在方法调用结束后便会自动被销毁。

下面,通过几个案例来看看

基本类型参数

package com.studyjava.demo;

public class Demo2
{
    public static void main (String[] args)
    {
        int n = 10;
        TripeVal(n); // n also is 10

        System.out.println(n);
    }

    public static void TripeVal(int n)
    {
        n *= 3;
    }
}

n还是等于3,没有问题,下面在看看如果传入的是对象会怎样。

对象参数

package com.studyjava.demo;

public class Demo2
{
    public static void main (String[] args)
    {
        var p = new People("James");
        p.setName("Paul");
        System.out.println(p.getName()); // paul
    }

}

class People
{
    private String name;

    public People(String name)
    {
        this.name = name;
    }

    public String getName ()
    {
        return this.name;
    }

    public void setName (String name)
    {
        this.name = name;
    }
}

这里和上面的情形相反,在方法中传入的参数是对象时,在方法中是可以修改对象的属性值的。这是因为,原变量以及副本同时引用同一个对象,所以副本可以修改被引用的对象。

根据这样的结果,许多人认为java和php是一样的,对于基本类型都是按值传递,但对于对象则是按引用地址来传递的。下面我们通过案例来论证,java方法的参数总是按照值传递的。

论证

这里,为了更好的论证,这里我分别使用Java以及php写一个程序。

java版如下:

package com.studyjava.demo;

public class Demo2
{
    public static void main (String[] args)
    {
        var p1 = new People("James");
        var p2 = new People("Paul");

        swap(p1, p2);
        System.out.println(p1.getName()); // James
        System.out.println(p2.getName());  // Paul
    }

    public static void swap (People p1, People p2)
    {
        var tmp = p1;
        p1 = p2;
        p2 = p1;
    }   
}

class People
{
    private String name;

    public People(String name)
    {
        this.name = name;
    }

    public String getName ()
    {
        return this.name;
    }

    public void setName (String name)
    {
        this.name = name;
    }
}

如果java中对象采用的是按引用地址传递的话,那么上述的swap方法就可以交换两个对象。但结果是两个对象并没有完成对换。因为java中对象也是按值传递的,所以你将副本对换,不会影响到原本对象。

下面再来看看php版的:

<?php

class People
{
    private $name;

    public function __construct(String $name)
    {
        $this->name = $name;
    }

    public function getName () : String
    {
        return $this->name;
    }

    public function setName (String $name) : void
    {
        $this->name = $name;
    }
}

function swap (People &$p1, People &$p2) : void
{
    $tmp = $p1;
    $p1 = $p2;
    $p2 = $tmp;
}

$p1 = new People("James");
$p2 = new People("Paul");
swap($p1, $p2);

echo $p1->getName() . PHP_EOL; // Paul
echo $p2->getName() . PHP_EOL; // James

小结

总结下java中对方法参数能做什么不能做什么:

  • 方法不能修改基本数据类型的参数(即数值型或布尔型)
  • 方法可以改变对象参数的状态。
  • 方法不能让一个对象参数引用一个新的对象。