Java 方法参数传递
- 在编程语言中,方法对于参数的调用分为 按值调用(call by value) 和 按引用调用(call by reference).
- 按值调用(call by value):方法接收的是调用者提供的值.
- 按引用调用(call by reference):方法接收的是调用提供的变量地址.
- Java 程序设计语言总是采用 按值调用(call by value).
- 引用《Java 核心技术卷1》
在 Java 中方法参数的传递总是 按值调用(call by value) 的。也就是说方法得到的是所有参数值的一个拷贝,方法不能修改传递给它的任何参数变量的内容。然而有时候这与我们所看到的不太一样。
在 Java 中方法参数共有两种类型:
基本数据类型(数值、字符、布尔);
对象引用
基本数据类型
public class ParamTest {
public static void main(String[] args){
double num = 10.0;
System.out.println("Before... --> num = "+num);
quadruple(num);
System.out.println("After... --> num = "+num);
System.out.println("--------------********----------------------");
double a = 20.0;
double b = 15.0;
System.out.println("Before... --> a = "+a+",b = "+b);
swap(a,b);
System.out.println("After... --> a = "+a+",b = "+b);
}
public static void quadruple(double num){
num*=4;
System.out.println("quadruple...--> num = "+num);
}
public static void swap(double a,double b){
double c = a;
a = b;
b = c;
System.out.println("swap...--> a = "+a+",b = "+b);
}
}
上面代码中方法 quadruple()
在方法内部将参数num
放大了四倍,swap()
方法试图将两个变量的值进行调换。
Before... --> num = 10.0
quadruple...--> num = 40.0
After... --> num = 10.0
--------------********----------------------
Before... --> a = 20.0,b = 15.0
swap...--> a = 15.0,b = 20.0
After... --> a = 20.0,b = 15.0
从运行结果来看,变量num
、a
、b
都没有发生改变。这是因为 基本数据类型传递过去的都是 值 的拷贝,所以方法内部无论怎么修改变量的值都不会对外部变量产生影响。
对象引用
package com.yun;
public class ObjParamTest {
public static void main(String[] args) {
Student stu = new Student("晓风","软件");
System.out.println("Before... --> stu = "+stu);
change(stu);
System.out.println("After... --> stu = "+stu);
System.out.println("--------------********----------------------");
Student stu1 = new Student("春雨","电子");
Student stu2 = new Student("夏雷","幼教");
System.out.println("Before... --> stu1 = "+stu1+",stu2 = "+stu2);
swap(stu1,stu2);
System.out.println("After... --> stu1 = "+stu1+",stu2 = "+stu2);
}
public static void change(Student stu){
stu.setName("秋风");
stu.setMojar("汽修");
System.out.println("change...--> stu = "+stu);
}
public static void swap(Student s1,Student s2){
Student t = s1;
s1 = s2;
s2 = t;
System.out.println("swap...--> s1 ="+s1+",s2 = "+s2);
}
}
class Student {
private String name;
private String mojar;
public Student(String name,String mojar){
this.name = name;
this.mojar = mojar;
}
/** Getter / Setter **/
@Override
public String toString(){
return "Studnet["+
"name = "+name+
",mojar = "+mojar+"]";
}
}
上面代码中,change()
方法对 stu
变量的信息进行了修改并输出,swap()
方法依旧是将两个变量进行交换,如果依照 基本数据类型 一样,那么所有的对象引用将不会发生改变,然而事情并不是像我们想的那样:
Before... --> stu = Studnet[name = 晓风,mojar = 软件]
change...--> stu = Studnet[name = 秋风,mojar = 汽修]
After... --> stu = Studnet[name = 秋风,mojar = 汽修]
--------------********----------------------
Before... --> stu1 = Studnet[name = 春雨,mojar = 电子],stu2 = Studnet[name = 夏雷,mojar = 幼教]
swap...--> s1 =Studnet[name = 夏雷,mojar = 幼教],s2 = Studnet[name = 春雨,mojar = 电子]
After... --> stu1 = Studnet[name = 春雨,mojar = 电子],stu2 = Studnet[name = 夏雷,mojar = 幼教]
可以看到,change()
方法竟然成功修改了变量stu
。既然 Java 总是按值传递的,那为什么这里对象引用有成功被修改了呢?是不是说 Java 对象引用是按引用传递的呢?答案肯定是不可能的,因为可以看到swap()
方法依旧没能调换两个变量的值。
change()
方法为什么能够改变对象引用的状态呢,这是因为 Java 中对象引用传递的是 地址值,当两个变量同时只向同一个 地址时,也就是说两个对象引用在操作一个对象。我认为它就像将一个对象变量赋值给另一个对象变量:
Student shily = new Student("Shily","Java");
Student stu = shily;
这里stu
的状态发生改变,shily
的状态跟着改变,这就相当于change()
方法。swap()
方法就像:
Student shily = new Student("Shily","Java");
Student stu = shily;
Student darn = new Student("Darn","C++");
stu = darn;
此时 变量stu
又重新指向了darn
的地址,然而这并不会对变量shily
产生任何影响。
在对象引用中,还有一个特殊的对象 String
String
public class ObjParamTest {
public static void main(String[] args) {
String str = "original";
System.out.println("Before... --> str = "+str);
change(str);
System.out.println("After... --> str = "+str);
}
public static void change(String str){
str = "change...";
System.out.println("change...--> str = "+str);
}
}
Before... --> str = original
change...--> str = change...
After... --> str = original
String 类并没有发生改变,String类像基本类型一样。
总结:
- 一个方法不能修改一个基本数据类型的参数
- 一个方法可以改变一个对象参数的状态
- 一个方法不能让对象参数引用一个新的对象