• Java中的参数传递到底是值传递还是参数传递


    先下结论:在 Java 语言中,本质只有值传递,而无引用传递

    1.值类型&引用类型

    1. 值类型就是Java 中的 8 大基础数据类型

      • 整数型:byte、short、int、long
      • 浮点型:float、double
      • 字符类型:char
      • 布尔类型:boolean

      所谓的值类型指的是在赋值时,直接在栈中(Java 虚拟机栈)生成值的类型

    2. 引用类型是指除值类型之外的数据类型

      • 类、接口
      • 数组
      • 字符串
      • 包装类(Integer、Double…)

      所谓的引用类型是指,在初始化时将引用生成栈上,而值生成在堆上的这些数据类型

    基本类型和引用类型内存中的不同
    int age = 10;
    String str = "hello";
    
    • 1
    • 2

    在这里插入图片描述

    如上图所示,age是基本类型,值就存在栈中的变量里

    而str是引用类型,栈中的变量保存的只是堆中实际对象的地址,一般称这种变量为引用,引用指向实际对象,实际对象中保存内容

    赋值时内存的变化
    int age = 24;
    String str = "world";
    
    • 1
    • 2

    在这里插入图片描述

    对于基本类型age,赋值运算符会直接改变变量的值,原来的值被覆盖掉

    对于引用类型str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象(“hello” 字符串对象)不会被改变(没有被任何引用所指向的对象是垃圾,会被垃圾回收器回收)

    2.关于值传递

    值传递(Pass By Value)指的是方法传参时,传递的是原内容的副本,因此对副本进行如何修改都不会影响原内容
    public class PassByValue {
    	private static int x=22;
    	public static void updateValue(int value){
    		value = 3 * value;
    	}
    	public static void main(String[] args) {
    		System.out.println("调用前x的值:"+x);
    		updateValue(x);
    		System.out.println("调用后x的值:"+x);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行结果

    调用前x的值:10
    调用后x的值:10
    
    • 1
    • 2

    执行流程

    在这里插入图片描述

    分析结论

    当传递方法参数类型为基本数据类型(数字以及布尔值)时,一个方法是不可能修改一个基本数据类型的参数

    3.关于引用传递

    引用传递(Pass By Reference)指的是方法传参时,传递的是参数本身,因此对参数进行任意修改都会影响原内容
    public class User {
        private String name;
        private int age;
        public User(String name, int age) {
          this.name=name;
          this.age=age;
        }
        public String getName() {
          return name;
        }
        public void setName(String name) {
          this.name = name;
        }
        public int getAge() {
          return age;
        }
        public void setAge(int age) {
          this.age = age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    public class PassByReference {
    	private static User user=null;
    	public static void updateUser(User student){
    		student.setName("change");
    		student.setAge(28);
    	}
    	public static void main(String[] args) {
    		user = new User("start",18);
    		System.out.println("调用前user的值:"+user.toString());
    		updateUser(user);
    		System.out.println("调用后user的值:"+user.toString());
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    运行结果

    调用前user的值:User [name=start, age=18]
    调用后user的值:User [name=change, age=28]
    
    • 1
    • 2

    很明显,user对象的值被改变了,也就是方法参数类型为引用类型的时候,引用类型对应的值将会被改变

    执行流程

    在这里插入图片描述

    分析结论

    当传递方法参数类型为引用数据类型时,一个方法将修改一个引用数据类型的参数所指向对象的值

    分析到这里,我们会发现,明明从代码中看到,既有值传递又有引用传递啊,可惜上面的代码其实是有一定的误导性的,下面再举一个例子来说明Java中只有值传递而没有引用传递

    public class PassByValue {
    	private static User user=null;
    	private static User stu=null;
    	/**
    	 * 交换两个对象
    	 * @param x
    	 * @param y
    	 */
    	public static void swap(User x,User y){
    		User temp =x;
    		x=y;
    		y=temp;
    	}
    	public static void main(String[] args) {
    		user = new User("user",26);
    		stu = new User("stu",18);
    		System.out.println("调用前user的值:"+user.toString());
    		System.out.println("调用前stu的值:"+stu.toString());
    		swap(user,stu);
    		System.out.println("调用后user的值:"+user.toString());
    		System.out.println("调用后stu的值:"+stu.toString());
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    运行结果

    调用前user的值:User [name=user, age=26]
    调用前stu的值:User [name=stu, age=18]
    调用后user的值:User [name=user, age=26]
    调用后stu的值:User [name=stu, age=18]
    
    • 1
    • 2
    • 3
    • 4

    看到这里,是不是又会有疑惑了?如果是按照引用传递来说的话,user和stu的值会被交换啊,但实际运行结果是没有交换

    通过下面的流程图可以看出,交换的只是user和stu的拷贝值,swap方法结束后,x、y都被释放,原来的user和stu仍然引用之前的对象

    x和y只是user和stu这两个引用的副本,并不是将user和stu这两个引用指向的对象传给了swap方法,并且对象的引用是在栈上存在的,引用副本的传递也就是值传递,而不是引用对象的传递,前面的之所以能够修改引用数据,是因为原始引用和引用副本均指向同一个对象,而对对象进行操作的时候,就是切切实实的改变了这个对象,即使方法结束,传入方法的引用的拷贝值被销毁,此时对象已经被改变,所以看起来像是符合引用传递的定义,但是并不是引用传递
    在这里插入图片描述

    4.总结

    在 Java 语言中只有值传递,主要是看这个值是什么,如果是简单值变量就拷贝了一份具体值,如果是引用变量就是拷贝了一份内存地址,方法传参时只会传递副本信息而非原内容。我们还知道了基础数据类型会直接生成到栈上,而对象或数组则会在栈和堆上都生成信息,并将栈上生成的引用,直接指向堆中生成的数据

    参考:java基本数据类型传递与引用传递区别详解_zejian_的博客-CSDN博客_java的值传递和引用传递区别

  • 相关阅读:
    Vue-cli全局配置整理
    ReactNative学习笔记
    泛微E8 查询分部总部部门信息
    基于Matlab实现图像目标边界描述
    太强了,全面解析缓存应用经典问题
    Java项目:JSP蛋糕甜品店管理系统
    Matlab基础用法
    Go编程项目实战教程
    【华为OD机试真题 python】n进制减法 【2022 Q4 | 200分】
    诊断数据库ODX—数据库框架(基于ISO22901详解)
  • 原文地址:https://blog.csdn.net/msq16021/article/details/126143447