一般来说,我们认为Java中传递参数有两种方式, 值传递和引用传递。但是后面又有人认为其实就一种类型,即值传递。那么到底结果是怎样的,我们来分析下。
实参与形参
在传递参数过程中,我们会涉及到实参与形参的概念,那么它们是怎样定义的?
- 形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数;
- 实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。
举个例子:
public class App {
public static void main(String[] args) throws Exception {
App app = new App();
app.add(1, 2);
Person person = new Person("Tome", 18);
app.printName(person);
}
// 值传递
private void add(int x, int y) {// 形参
System.out.println("x + y =" + (x + y));
}
// 引用传递
private void printName(Person person) {// 形参
System.out.println("name = " + person.name + ",age = " + person.age);
}
static class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
}
改变x,y的值,打印结果
public class App {
public static void main(String[] args) throws Exception {
App app = new App();
int x = 1;
int y = 2;
app.add(x, y);
System.out.println("main::x =" + x + ",y = " + y);
Person person = new Person("Tome", 18);
app.printName(person);
}
// 值传递
private void add(int x, int y) {// 形参
x = 3;
y = 4;
System.out.println("x =" + x + ",y = " + y);
}
// 引用传递
private void printName(Person person) {// 形参
System.out.println("name = " + person.name + ",age = " + person.age);
}
static class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
}
打印结果
x =3,y = 4
main::x =1,y = 2
name = Tome,age = 18
可以看到,在方法内部x,y改变后,原x,y的值不变,这就是我们说的值传递。
下面我们看下引用传递,示例如下:
public class App {
public static void main(String[] args) throws Exception {
App app = new App();
int x = 1;
int y = 2;
app.add(x, y);
System.out.println("main::x =" + x + ",y = " + y);
Person person = new Person("Tome", 18);
app.printName(person);
System.out.println("main::name = " + person.name + ",age = " + person.age);
}
// 值传递
private void add(int x, int y) {// 形参
x = 3;
y = 4;
System.out.println("x =" + x + ",y = " + y);
}
// 引用传递
private void printName(Person person) {// 形参
person.name = "Jerry";
person.age = 20;
System.out.println("name = " + person.name + ",age = " + person.age);
}
static class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
}
将Person传入之后改变它内部的值,打印结果如下:
x =3,y = 4
main::x =1,y = 2
name = Jerry,age = 20
main::name = Jerry,age = 20
结果发现原来的Person也改变,这似乎证明了引用传递的正确性,但是别急,我们在来修改下:
public class App {
public static void main(String[] args) throws Exception {
App app = new App();
int x = 1;
int y = 2;
app.add(x, y);
System.out.println("main::x =" + x + ",y = " + y);
Person person = new Person("Tome", 18);
app.printName(person);
System.out.println("main::name = " + person.name + ",age = " + person.age);
}
// 值传递
private void add(int x, int y) {// 形参
x = 3;
y = 4;
System.out.println("x =" + x + ",y = " + y);
}
// 引用传递
private void printName(Person person) {// 形参
person = new Person();
person.name = "Jerry";
person.age = 20;
System.out.println("name = " + person.name + ",age = " + person.age);
}
static class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
}
我们在方法内部重新new一个新的Person,我们看下打印结果:
x =3,y = 4
main::x =1,y = 2
name = Jerry,age = 20
main::name = Tome,age = 18
怎么回事,为什么又不一样了?因为第一次其实是把实参对象引用的地址当做值传递给了形式参数。而第二次我们重新构造一个Person,他们指向的地址不一样了,当然不会改变原来对象的值了。
总结
所以说,Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。
网友评论