值传递
在Java中,参数传递是值传递(Pass-by-Value)。这意味着当你将一个变量作为参数传递给一个方法时,实际上传递给方法的是该变量的值(也就是存储在变量中的数据),而不是变量本身。
值传递(pass by value):是指在调用函数时将实际参数 复制 一份传递到函数中,这样在函数中如果对 参数 进行修改,将不会影响到实际参数。
**引用传递 (pass by reference) **:是指在调用函数时将实际参数的地址 直接 传递到函数中,那么在函数中对 参数 所进行的修改,将影响到实际参数。
结论:
- Java 中的参数传递是按值传递的。
- 如果参数是基本类型,传递的是基本类型的字面量值的拷贝。
- 如果参数是引用类型,传递的是引用的对象在堆中地址的拷贝。
其实就是操作的是一块内存还是新开辟了一块内存的区别。
基本数据类型
对于基本数据类型(如int、double、boolean等),这是直观的,因为它们存储的就是值本身,所以传递它们就是传递值。
public class ParamTest2 {
public static void main(String[] args) {
// i 为 int 为基本数据类型,值 10 直接保存在变量中(栈)
int i = 10;
// 复制 i 的值 10 给形式参数 i1
change(i);
System.out.println("出了方法i:"+i);
}
public static void change(int i1){
i1 = 20;
System.out.println("进入方法i:"+i1);
}
}
执行逻辑:
- i 为 int 为基本数据类型,值 10 直接保存在变量中(栈)
- 复制 i 的值 10 给形式参数 i1
- change(int i1) 对 i1 进行修改
- i 没有发生改变
引用数据类型
对于引用数据类型(如对象、数组等),传递的是引用的值,也就是对象的内存地址。这可能会导致一些混淆,因为虽然传递的是引用的值,但仍然是值传递。这意味着在方法内部,你可以通过引用修改对象的状态,但如果你在方法内重新分配了引用,它不会影响原始引用。
String
public class ParamTest3 {
public static void main(String[] args) {
String str = "ab";
change(str);
System.out.println("出了方法str:"+str);
}
public static void change(String str1){
System.out.println("初始进入方法str:"+str1);
// 对 i1 进行赋值
str1 = "cd";
System.out.println("赋值之后尚未出方法str:"+str1);
}
}
初始进入方法str:ab
赋值之后尚未出方法str:cd
出了方法str:ab
- str 初始化,指向堆中 "ab" 的位置,内存地址 0x123456
- 复制 str 的内存地址 0x123456 到 str1
- 改变了形参 str1 的地址到 0x988766
- 此时 str 为0x123456,str1 为0x988766
实体Bean
public class ParamTest4 {
public static void main(String[] args) {
UserParam userParam = new UserParam();
userParam.setAge(18);
userParam.setName("小明");
System.out.println("前:"+userParam.toString());
change(userParam);
System.out.println("后:"+userParam.toString());
}
public static void change(UserParam userParam1){
userParam1.setName("小红");
}
}
// 前:UserParam{name='小明', age=18}
// 后:UserParam{name='小红', age=18}
- userParam 内存地址 0x12312 指向堆中 age = 18,name = "小明"
- 内存地址 0x12312 传递给 userParam1,此时 userParam1 内存地址也为 0x12312
- 此时修改的是内存地址 0x12312 指向的内容,并没有新的开辟内存
- 值发生了改变
public class ParamTest5 {
public static void main(String[] args) {
UserParam userParam = new UserParam();
userParam.setAge(18);
userParam.setName("小明");
System.out.println("前:"+userParam.toString());
change(userParam);
System.out.println("后:"+userParam.toString());
}
public static void change(UserParam userParam1){
userParam1 = new UserParam();
userParam1.setName("小红");
}
}
// 前:UserParam{name='小明', age=18}
// 后:UserParam{name='小明', age=18}
和上面最大的区别是 userParam1 = new UserParam(); 新开辟了一个内存地址 0x88888