1、典型回答
值传递(Pass by value)和引用传递(Pass by reference)是关于参数传递方式的两个概念
- 值传递:将传递参数的值,复制一份到方法的参数中。换句话说,值传递的是原始数据的一个副本,而不是原始数据本身
- 引用传递:将实际参数的引用(内存地址)传递给方法,这意味着方法内部对参数的修改会影响原始数据本身,也就是说引用传递传递的是原始数据,而非原始数据的副本
也就是说,值传递和引用传递最大的区别是传递的是自身,还是复制的副本,如果传递的是自身,则为引用传递,如果传递的是复制的副本,则为值传递
而在 Java 语言中,只有值传递,没有引用传递!
例如,在以下示例中,传递基础数据类型 int 的参数,之后修改传递的参数,然后再在原来的方法中,打印参数的结果,实现代码如下:
以上程序的执行结果如下:
从上述结果可以看出 int 是值传递
如果说,上面传递的是基本数据类型,接下来我们传递一个对象(引用类型):
以上程序的执行结果如下:
从上述结果可以看出,当传递的是 Integer 对象时,其依然是值传递,所以在 Java 语言中,并没有引用传递
因此,无论是基础数据类型,还是引用数据类型(对象),都为值传递,而非引用传递
2、全面剖析
值传递和引用传递的关键是,传递的是副本还是其本身,如果是副本则为值传递,如果是其本身则为引用传递,而 Java 语言中,只有值传递,也就是说它始终传递的都是副本
那么,问题来了,为什么在以下代码中,当我传递的是一个数组的时候,就和之前的结果不一样了呢?
以上程序的执行结果为:
调用方法前:磊哥
方法中修改为:磊神
调用方法后:磊神
这样就出问题了,当传递了数组之后,明显是 “引用传递”,而非值传递,这到底是怎么回事?
别着急,当我们把新方法中的代码做了以下调整之后,运行结果又不一样了,如下代码所示:
以上程序的执行结果为:
调用方法前:磊哥
方法中修改为:磊神
调用方法后:磊哥
你会发现,当我们在新方法中仅仅添加了一行 “n = new char[2]; ”代码时,它又变成了值传递,这是怎么回事?
原因分析
如果是引用传递,那么我在新方法中无论如何修改,那么都应该是影响原对象才对,而刚才我稍微调整了代码之后就发现并非引用传递,而是值传递,这是因为当传递数组时,其传递的是 “引用副本”,而非真正的引用对象(也就是其本身)
也就是说,当传递数组时,其实传递的是“引用副本”,注意是 “引用” 的副本。然后新方法通过这个副本指向原数组。不是对象本身的副本!!!是对象引用的副本!!!如下图所示:
然而,在调用了“n = new char[2]; ”代码之后,给变量在堆上创建了新对象,此时就不再使用原来的引用副本了,这个时候,再修改新方法中的变量就不影响原变量了,如下图所示:
所以,在Java中,只有值传递,它始终传递的都是副本,而非原(引用)对象
3、知识扩展
3.1、形参 VS 实参
在 Java 中,形参(formal parameters)和 实参(actual arguments)是方法定义和方法调用中的两个概念,形参是方法定义中声明的参数,用于接受方法调用时传递的实参的值,而实参是方法调用时提供给方法的具体参数值
3.2、参数类型:固定个数参数和可变参数
在 Java 中,方法的参数可以有以下几种类型:
- 基本数据类型参数:包括整型(byte、short、int、long)、浮点型(float、double)、字符型(char)以及布尔型(boolean)等
- 引用类型参数:包括类、接口、数组等。引用类型的参数实际上传递的是对象的引用值,而不是对象本身
- 泛型参数:Java5 及以上版本引入的泛型机制可以用于定义带有参数化类型的方法。这样可以在方法中使用泛型进行更加灵活的类型处理
- 可变参数(Varargs)参数:Java5 及以上版本引入的一种特殊的参数类型,在方法声明中使用...表示。它允许方法接受可变数量的同类型参数,将这些参数作为数组进行处理
以上类型中,前三种属于固定参数类型,而最后一种为可变参数类型
标签:副本,Java,传递,参数,引用,方法 From: https://blog.csdn.net/dream_ready/article/details/135633484