值传递

在Java中,参数传递是值传递(Pass-by-Value)。这意味着当你将一个变量作为参数传递给一个方法时,实际上传递给方法的是该变量的值(也就是存储在变量中的数据),而不是变量本身。

  1. 值传递(pass by value):是指在调用函数时将实际参数 复制 一份传递到函数中,这样在函数中如果对 参数 进行修改,将不会影响到实际参数。

  2. **引用传递 (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);
    }
}

执行逻辑:

  1. i 为 int 为基本数据类型,值 10 直接保存在变量中(栈)
  2. 复制 i 的值 10 给形式参数 i1
  3. change(int i1) 对 i1 进行修改
  4. 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
  1. str 初始化,指向堆中 "ab" 的位置,内存地址 0x123456
  2. 复制 str 的内存地址 0x123456 到 str1
  3. 改变了形参 str1 的地址到 0x988766
  4. 此时 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}
  1. userParam 内存地址 0x12312 指向堆中 age = 18,name = "小明"
  2. 内存地址 0x12312 传递给 userParam1,此时 userParam1 内存地址也为 0x12312
  3. 此时修改的是内存地址 0x12312 指向的内容,并没有新的开辟内存
  4. 值发生了改变
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

Last Updated:
Contributors: 拔土豆的程序员