一. 先看看C++的一个实例(方便理解Java)
1. 例子argtest.cpp中的swap1函数是最常见的一种,形参copy了一份实参,也即main中的a1_1和swap1中的a1_1在内存中是两份不同的数据,但传入时它们保存的值是相等的,仅此而已,所以你在swap1函数中怎么捣鼓a1_1,都不会影响到main中的a1_1;
Java基本类型的参数传入,即int、boolean、char等,可以理解成这种方法,也就是所谓的“值传递”;
2. 例子argtest.cpp中的swap2函数,其实int换成某个class也同样适用,你可以swap2中的“int *a1_2” 脑补成 "User *user1"也是完全没问题的;
swap2是用指针传递参数,尽管如此,和swap1本质上也是一样的:“指针”也是数据,所以swap2的a1_2即形参,也是copy了一份实参,只不过这次实参是指针,但传入时它们保存的值是相等的,也就是指向的内存是同一份。也仅此而已,实参和形参依旧是2份不同的东东,所以在swap2那样“你等于我我等于你”是起不到作用的;要想起作用就得用到C/C++的取值符“ * ”(星号);
Java引用类型的参数擦混入,可以理解成这种方式,也就是所谓的“引用传递”,其中Java的引用直接看做“指针”;(其实我感觉本质依旧是值传递)
3. 例子argtest.cpp中的swap3函数,用到了c++的引用方法,本质其实也是传入了指针;
要明确的是:Java没有swap3这种方式,还需要注意的是,Java的引用和c++的引用是两回事,不要搞混了;本文针对的是Java,所以此方式不赘述;
argtest.cpp:
#include <iostream>
using namespace std;
void swap1(int a1_1, int a2_1) {
int temp = 0;
temp = a1_1;
a1_1 = a2_1;
a2_1 = temp;
}
void swap2(int *a1_2, int *a2_2) {
int *temp = 0;
temp = a1_2;
a1_2 = a2_2;
a2_2 = temp;
}
void swap3(int &a1_3, int &a2_3) {
int temp = 0;
temp = a1_3;
a1_3 = a2_3;
a2_3 = temp;
}
int main()
{
int a1_1 = 1;
int a2_1 = 2;
int a1_2 = 1;
int a2_2 = 2;
int a1_3 = 1;
int a2_3 = 2;
swap1(a1_1, a2_1);
cout<<a1_1<<" "<<a2_1; //输出结果: 1 2
cout<<"\n";
swap2(&a1_2, &a2_2);
cout<<a1_2<<" "<<a2_2; //输出结果: 1 2
cout<<"\n";
swap3(a1_3, a2_3);
cout<<a1_3<<" "<<a2_3; //输出结果: 2 1
cout<<"\n";
}
二. Java的形参和实参
1. 对比前后2个例子的前2个方法,你或许可以找到很多共同点,我认为前者的swap1对应后者的swap1,前者的swap2对应后者的swapUser;
2. 不管传入方法的是基本类型还是引用类型,形参和实参都是两份数据,只不过“存的内容”一样而已;
3. 传入引用其实可以理解为传入的是"指针",引用形参和引用实参是两份“指针”,只不过它们指向同一份数据;
4. ArgTest.java中的swapUserAge方法之所以能够成功交换数据,因为“u1.age”表示的是形参指向的数据,而不是形参本身,形参和实参虽然是两份数据,但是它们指向的数据是同一份的,所以“看起来是修改了”。其实swapUserAge中依旧无法改变main中栈里面的那个实参user1,改变的只是user1指向的那份堆内存;
ArgTest.java:
public class ArgTest {
public static void main(String[] args) {
int a1 = 1;
int a2 = 2;
swap1(a1, a2);
System.out.println(a1 + " " + a2); //输出结果: 1 2
User user1 = new User(1);
User user2 = new User(2);
swapUser(user1, user2);
System.out.println(user1.age); //输出结果: 1
swapUserAge(user1, user2);
System.out.println(user1.age); //输出结果: 2
}
private static void swap1(int a1, int a2) {
int temp;
temp = a1;
a1 = a2;
a2 = temp;
}
private static void swapUser(User u1, User u2) {
User temp;
temp = u1;
u1 = u2;
u2 = temp;
}
private static void swapUserAge(User u1, User u2) {
int tempAge = u1.age;
u1.age = u2.age;
u2.age = tempAge;
}
}
class User {
public int age;
public String name;
public User(int age) {
this.age = age;
}
public void showUser() {
System.out.println("I am User");
}
}
三. Java的值类型数据和引用类型数据
引用王垠的一句话:
我认为他说的很有道理,感兴趣的可以点进去看一下他那篇博文,写得非常不错。