我们平时看到的Java说明书对于Java的传递类型的介绍是按值传递,但是我们在平时总是会出现Java是按引用传递的错觉,这是因为我们没有搞清楚这两种传递的概念
按值传递
按值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
也就是说在我们调用的方法中,我们用的其实不是一个参数,而是一个新的参数,与实参只是数值相同
public class StringBase {
public static void main(String[] args) {
int c = 66; //c 叫做实参
String d = "hello"; //d 叫做实参
StringBase stringBase = new StringBase();
stringBase.test5(c, d); // 此处 c 与 d 叫做实参
System.out.println("c的值是:" + c + " --- d的值是:" + d);
}
public void test5(int a, String b) { // a 与 b 叫做形参
a = 55;
b = "no";
}
}
【运行结果】
c的值是:66 — d的值是:hello
可以看出通过方法传递后,int 类型与 String 类型的原值并没有受到前面 test5 方法执行后的影响,还是输出了原值。这种形为通常被说成值传递。如果原值经过 test5 方法后被改变了,这种形为通常被描述为引用传递。
按址传递
按址传递是指是指在调用函数时将实际参数的地址直接传递到函数中(的形参),那么在函数中对参数所进行的修改,将影响到实际参数。
就是形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。但Java没有指针一说,所以可以直接理解为操作同一地址
public class StringBase {
public static void main(String[] args) {
int[] m = new int[1,2,3];
StringBase stringBase = new StringBase();
stringBase.test5(n);
System.out.println("m的值是:" + m);
}
public void test5(int [] n) {
n[1] = 1;
}
}
在数组的传递中,我们修改形参n中的值会发现m中的值也发生改变,那么是不是说Java其实是也存在按引用传递
我们对这部分发生混淆是很正常的,这是因为我们对Java数据的存储方式没有一个很清楚的认知
Java的数据类型分为基本数据类型和引用数据类型
基本数据类型在存储时是讲变量名称和变量共同存放在栈中
当我们数值传递时,创建的形参也在栈中,但即使它们的数值是一样的,也只是指向同一个数值地址,当形参发生改变时,则会新开辟一块数值地址存放新的数据,形参指向新的数据,所以实参不会受到影响
对于引用数据类型 类 数组 接口来说 他们的名称放在栈中,数据放在堆中,形参和实参指向堆中同一位置,在改变形参的部分时 实参也跟着改变所以我们认为他们是按址传递
但我们应该清楚的是引用数据类型在栈中的存储是下面这样的
这是在形参和实参之间的关系
String类型是个例外,它是引用类型但它在修改形参时,不会影响实参,
因为String是final类型
总结
Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按 值传递的。
下面再总结一下Java中方法参数的使用情况:
一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
一个方法可以改变一个对象参数的状态。
一个方法不能让对象参数引用一个新的对象。