按值传递
一些小白在写java程序时 会遇到这样的问题:
public static void method( int as){
as = 100;
}
public static void main(String[] args){
int as = 50;
method(as);
System.out.println(as);
}
以上代码输出结果还是50
,并没有改变as的值。按照想法我们把as作为参数传递到函数中并且更改了值啊?为什么没有效果呢?
解答:
- 我们在栈中声明了一个as变量,给它进行初始化后就在堆中分配了空间
- 我们将as作为参数传递执行method方法时,相当于method方法中的as拷贝了一份我们声明的as
- 但在方法中我们将拷贝的as重新赋值,在堆中的指向会发生变化。
这就是按值传递的原理了,我们在方法中操作as这个参数并不能够改变我们声明的as的指向,参数传递过来只是相当于一份拷贝,不会影响声明的as的值,所以输出结果还是50
,没有发生变化。
按引用传递
我们了解了按值传递,那么按引用传递会不会发生和按值传递一样的情况呢?
我们来实验一下!
首先我们会在Student类中给定age一个初值,并且写好set、get方法。
private int age = 20;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
按照按值传递的思路完成代码:
public static void method_01(Student stu){
stu.setAge(10);
}
public static void main(String[] args){
Student student = new Student();
method_01(student);
System.out.println(student.getAge());
}
最后结果输出为10
,它竟然修改成功了,看来按引用传递和按值传递有不同之处。那么到底哪里不同呢?
解答:
- 同样,new了一个新的对象,肯定在栈中存在了,并且student这个对象的age是有初始值的,在堆中肯定分配了一块空间来存储。
- 将student作为参数传入method_01这个方法中,首先肯定的是,方法中的参数是student的拷贝。
- 执行method_01方法中的
stu.setAge(10);
,从上图我们可以发现stu的指向还是age。所以在执行在stu.setAge(10);
时会更改age的值
以上就是按引用传递的基本原理,所以按引用传递会改变我们对象初始化的初始值
总结:
- 按值传递时,我们在方法中改变值的大小并不会影响原来的变量值的大小。方法参数的指向与原本的变量指向不是同一个,改变参数指向的值并不会对原本变量的值产生影响。
- 按引用传递时,方法中改变值是会改变对象的初始值,因为方法参数的指向与对象的指向是同一个,通过参数修改堆中的属性值,对象也会受到影响。