深入理解Java中方法的参数传递机制


深入理解Java中方法的参数传递机制

文章插图
 
形参和实参
我们知道,在JAVA中定义方法时,是可以定义参数的,比如:
public static void main(String[] args){ }这里的args就是一个字符串数组类型的参数 。
在程序设计语言中,参数有形式参数和实际参数之分,先来看下它们的定义:
形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数,简称“形参” 。
实际参数:在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”,简称“实参” 。
举个栗子:
public class ParamTest { public static void main(String[] args) { ParamTest pt = new ParamTest(); // 实际参数为“张三” pt.sout("张三"); }? public void sout(String name) { // 形式参数为 name System.out.print(name); } }上面例子中,ParamTest类中定义了一个sout方法,该方法有个String类型的参数name,该参数即为形参 。在main方法中,调用了sout方法,传入了一个参数“张三”,该参数即为实参 。
那么,实参值是如何传入方法的呢?这是由方法的参数传递机制来控制的 。
值传递和引用传递
参数传递机制有两种:值传递和引用传递 。我们先来看下程序语言中是如何定义和区分值传递和引用传递的:
值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数 。
引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数 。
那么,在我们大Java中,到底是值传递还是引用传递呢?
Java中是值传递还是引用传递?
有了上面的概念,我们就可以一起来探究一下,Java中方法参数到底是值传递还是引用传递了 。
先看如下代码:
public class ParamPass1 { public static void main(String[] args) { ParamPass1 p = new ParamPass1(); int i = 10; System.out.println("pass方法调用前,i的值为=" + i); p.pass(i); System.out.println("pass方法调用后,i的值为=" + i); }? public void pass(int i) { i *= 3; System.out.println("pass方法中,i的值为=" + i); }}上面代码中,我们在类中定义了一个pass方法,方法内部将传入的参数i的值增加至3倍,然后分别在pass方法和main方法中打印参数的值,输出结果如下:
pass方法执行前,i的值为=10pass方法中,i的值为=30pass方法执行后,i的值为=10从上面运行结果来看,pass方法中,i的值是30,pass方法执行结束后,变量i的值依然是10 。
可以看出,main方法里的变量i,并不是pass方法里的i,pass方法内部对i的值的修改并没有改变实际参数i的值,改变的只是pass方法中i的值(pass方法中,i=30),因为pass方法中的i只是main方法中变量i的复制品 。
因此同学们很容易得出结论:Java中,一个方法不可能修改一个基本数据类型的参数,所以是值传递 。
然而,结论下的还太早,因为方法参数共有两种类型:
  1. 基本数据类型
  2. 引用数据类型
前面看到的只是基本数据类型的参数,那对于引用类型的参数,又是怎么样的呢?看如下代码:
public class ParamPass2 { public static void main(String[] args) { ParamPass2 p = new ParamPass2();? User user = new User(); user.setName("张三"); user.setAge(18);? System.out.println("pass方法调用前,user=" + user.toString()); p.pass(user); System.out.println("pass方法调用后,user=" + user.toString()); }? public void pass(User user) { user.setName("李四"); System.out.println("pass方法中,user = " + user.toString()); }}?class User { /** * 姓名 */ private String name;/** * 年龄 */ private int age;? public String getName() { return name; }? public void setName(String name) { this.name = name; }? public int getAge() { return age; }? public void setAge(int age) { this.age = age; }? @Override public String toString() { return "User{" + "name='" + name + ''' + ", age=" + age + '}'; }}上面代码中,定义了一个User类,在main方法中,new了一个新的User对象user,然后给user对象的成员变量赋值,pass方法中,修改了传入的user对象的属性 。
运行main方法,结果如下:
pass方法调用前,user= User{name='张三', age=18}pass方法中,user = User{name='李四', age=18}pass方法调用后,user= User{name='李四', age=18}


推荐阅读