从学了Java一直以来,我一直都以为Java中基本类型为值传递,引用类型为引用传递,今天发现问题后查了很多资料,终于明白了:Java中只有值传递,没有引用传递。
首先我们需要明白什么是值传递,什么是引用传递。
值传递:调用方法之后,如果新创建了一个变量或者对象,(也就是说:被调用者中的变量(原始值)是调用者中变量的一份拷贝)是值传递。
引用传递:调用方法之后,如果直接将地址传递,不会在产生一个新变量(调用者和被调用者其实用的是同一个变量)是引用传递。
造成我困扰的原因在于Java中有两大种数据类型,一种是基本数据类型(如int float boolean等),一种是引用数据类型(Integer String等)
对于基本数据类型没啥讨论的,都是值传递,下面用一个例子说明:
public static void swap(int a,int b)
{
int temp=a; a=b; b=temp;
System.out.println("a = " + a);//输出a=20
System.out.println("b = " + b);//输出b=10 }
public static void main(String[] args)
{
int a=10,b=20; swap(a,b);
System.out.println("a = " + a);//输出a=10
System.out.println("b = " + b);//输出b=20 }
毫无疑问,这是值传递。
接下来看这段代码
public static void main(String[] args)
{
int[] arr = { 1, 2, 3, 4, 5 };
System.out.println(arr[0]);
change(arr);
System.out.println(arr[0]);
}
public static void change(int[] array)
{
// 将数组的第一个元素变为0
array[0] = 0;
}
就是这个例子一直让我以为Java中如果是基本类型就是值传递,引用类型是引用传递,其实不是的,形参只是地址的拷贝
在调用change() 方法时,实参 a 在栈中创建了一个新的副本,但它们指向的对象是一致的。
我们用下面的例子证明
public static void main(String[] args) {
People a = new People(15);
People b = new People(15);
test(a, b);
System.out.println(a.getAge());
System.out.println(b.getAge());
}
private static void test (Writer a1, Writer b1) {
a1.setAge(30);
b1 = new People(18);
b1.setAge(30);
输出:
30
18
再调用test方法时,a,b都在栈中创建了一个副本
调用方法后
在test方法中,对象a没有改变,形参 b1 指向了一个新的对象,随后 b1 的 age 被修改为 30。修改 a1 的 age,意味着同时修改了 a 的 age,因为它们指向的对象是一个;修改 b1 的 age,对 b 却没有影响,因为它们指向的对象是两个。
所以就很明显了,这都是创建了一个副本,也就证明了在Java中都是值传递。