想弄清这个问题之前,要先搞懂两个概念,什么是按值传递,什么是按引用传递.
按值调用/传递(call by value):是指在调用函数时将实际参数的值复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
按引用调用/传递(call by reference):是指在调用函数时将实际参数的地址(c语言中指针)直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数
下面就来看两个例子,希望帮助小伙伴们弄清这个问题
引用数据类型
public class BianLiFeng {
public static void main(String[] args) {
People people = new People("yht");
System.out.println("before:"+people.getName());
change(people);
System.out.println("after:"+people.getName());
}
public static void change(People people){
people.setName("qcby");
System.out.println("change:"+people.getName());
}
}
class People{
public String name;
public People(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
这个代码结构应该挺清晰的,大家可以自己先想一下,代码会输出什么.
结果
根据结果我们可以得到一个结论就是:当传递方法参数类型为引用数据类型时,方法可以修改参数
我们可以这样理解,当我们new一个对象的时候,会在堆中创建对象,同时把栈中的引用指向堆中的实例,当我们把people对象传给函数的时候,实际上我们是把对象的地址传给了函数,也就是说我们传递了一个实参的副本,但是副本和实参同时指向堆中的同一个地址,那我们通过副本来修改地址的内容当然会改变实参的值,但是我们无法改变实参指向的堆中的地址。
基本数据类型
public static void main(String[] args) {
int x=66;
System.out.println("before:"+x);
change(x);
System.out.println("after:"+x);
}
public static void change(int x){
x=23;
System.out.println("change:"+x);
}
这段代码小伙伴们还是先想一下会输出什么。
结果
其实也很好理解,我们在给函数传递基本数据类型的时候,我们还是传递给函数一个实参的副本,所以你对一个副本的值进行修改,对我实参肯定是没有影响的。
再验证
public static void main(String[] args) {
People people = new People("yht");
System.out.println("before:"+people.getName());
change(people);
System.out.println("after:"+people.getName());
}
public static void change(People people){
people=new People("qcby");
System.out.println("change:"+people.getName());
}
}
class People{
public String name;
public People(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
请小伙伴们仔细看这段代码,和上面引用类型的验证有什么区别,没错这次我们在函数中让传入的参数指向一个新地址,也就是让参数指向一个新的地址,结果大家想一下,如果想明白了,就真正的理解了java是按值传递还是按引用传递了
结果
没错,当我们在函数中试图修改引用类型参数的地址的时候,那肯定是修改不了的,因为java是按值传递,他传递的知识实参的一个副本,但是我们可以修改地址里的内容,因为副本和实参指向相同的地址,但是如果我们想改实参的地址是改不了的。
希望这三个例子可以帮助小伙伴们解决这个问题~