参考 https://www.zhihu.com/question/31203609
参考 http://www.cnblogs.com/xwdreamer/archive/2012/04/01/2428857.html
参考 https://www.cnblogs.com/binyue/p/3862276.html
什么是值传递,什么是引用传递
- 值传递(pass by value): 是指在方法调用的过程中,是将
参数copy一份
传递到函数中,在函数中对参数进行修改,将不会影响
到实际的参数。 - 引用传递(pass by reference): 是指在方法调用过程中,是将
参数的实际地址
传递到函数中,在函数中对参数进行修改,会影响
到实际参数。
那么java到底是值传递还是引用传递呢? 在业界有很多种说法,在开撕之前,我们先回忆下java的内存机制。
Java的内存机制
Java 把内存划分成两种:一种是栈内存,另一种是堆内存。
这种分法比较粗浅,java内存区域实际远比这个复杂。
这种分发比较流行只能说明大多数程序员最关注的、与内存分配关系最密切的内存区域就是这两块。
- 基本类型的变量和对象的引用变量都是在函数的
栈内存中分配
堆内存
用来存放由new创建的对象和数组。
例: 对象创建
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class PassByWhat {
public static void main(String[] args) {
int num = 9 ;
Person person = new Person("trump", 73);
}
}
此时他们在内存中的分布,如下图:
例-赋值运算符"="的作用
public static void main(String[] args) {
int num = 9 ;
Person person = new Person("trump", 73);
num = 8 ;
person = new Person("hillary", 72);
}
此时他们在内存中的分布,如下图:
- 对于
基本类型 num
,赋值运算符会直接改变变量的值,原来的值被覆盖掉。 - 对于
引用类型 person
,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。
pass_by_what ?
例:验证
public class PassByWhat {
public static void main(String[] args) {
int num = 1;
f1(num);
System.out.println("f1()修改后:num="+num);
Person person = new Person("trump", 73);
f2(person);
System.out.println("f2()修改后:"+person);
f3(person);
System.out.println("f3()修改后:"+person);
}
static void f1(int n) {
n = -999;
}
static void f2(Person p){
p.age = 66;
}
static void f3(Person p){
p = new Person("hillary", 72);
}
}
运行结果:
f1(int)
:修改未起作用 — 说明是值传递
f2(Person)
:修改起作用 — 说明是引用传递
f3(Person)
: 修改未起作用 — 说明是值传递
从上述的结果分析,得出一个结论java似乎既不是我们之前理解的那种值传递也不是引用传递
.
那么java到底pass_by_what ?
pass_by_what
实参和形参的概念
f2()为什么修改成功
在调用方法f2()
时,实际参数的引用地址(person:0x123
)被传递给方法中相对应的形式参数(p:0x123
):
执行完f2()
逻辑p.age = 66;
之后,p的引用地址值并未发生改变。
在方法执行中,形参和实参指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。
f3()为什么修改不成功
在方法执行中,形参(0x123
)和实参(0x789
)指向的不是同一块内存地址,所以方法执行的结果不会想象到实参。
结论
- 基本数据类型传值,对形参的修改不会影响实参;
- 引用类型传引用
- 形参和实参指向
同一个内存地址
,所以对参数的修改会影响
到实际的对象; - 形参和实参指向
不同内存地址
的,则对参数的修改不会
影响到实际的对象;
- 形参和实参指向