java中向方法传递参数是,是将参数的副本传递进去,即方法运行时会被分配一块内存区域保存一个参数值的copy,修改副本值,对原参数并没有影响。
要理解形参和实参,并在编码中避免一些必要的错误,需要弄清两个概念。
1、什么是形参和实参
2、方法调用时参数传递的过程
3、值传递和引用传递
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; public class ArgumentsTest { public static void main(String[] args){ Emp empA = new Emp("ke",22); int num = 22; apply(empA); System.out.println(empA); apply2(num); System.out.println(num); } public static void apply(Emp emp){ emp = new Emp("li",77); } public static void apply2(int num){ num = 33; } @AllArgsConstructor @NoArgsConstructor @Data static class Emp{ private String name; private int age; } }
首先什么是形参什么是实参?
在上述代码中,apply方法的参数emp,就是形参,形式参数,它代表实际参数来参与方法的逻辑;而实参就是在调用方法时,向方法传递的参数值,即main方法中empA。
在方法运行时参数是如何传递的呢?
首先,每个变量都会在内存中对应一个内存空间,用来存放参数值。而在方法运行时,虚拟机会在栈中创建内存空间保存一个实参的副本,该内存空间会在方法调用结束时销毁,该对副本的修改不会影响原参数的值。
值传递和引用传递?
在java中有两种数据类型,基本类型和引用类型。当变量是基本类型是,变量对应的内存空间保存的变量值,如上述代码中num保存22;当变量是引用类型时,内存中保存的是实际对象在堆中的地址。
而在方法调用时,传递的都是变量对应内存中的值,不同的是基本类型参数传递值给方法,引用类型参数传递对象内存地址给方法。
引用类型包括:类类型、接口类型、数组。
运行上述代码:
结果:
ArgumentsTest.Emp(name=ke, age=22)
22
原参数值并没有被改变。
引用类型参数被改变值的情况
改变apply方法的逻辑:
public static void apply(Emp emp){ emp.setName("li"); emp.setAge(44); }
结果:
ArgumentsTest.Emp(name=li, age=44)
原参数被改变了,为什么。
因为,方法中的参数虽然是原参数的副本,但是实例对象在堆中的数据只有一份,如果直接去修改对象的属性值,就可以修改原参数值了。
类似的,对数组,可以修改单个数组元素的值,也是有效的。
对于包装类,可以通过反射修改内部的value,可以达到相同的效果。