首页 > 编程知识 正文

引用传递,函数传递参数有哪些方式

时间:2023-05-06 17:32:57 阅读:31113 作者:3219

一、结论是,JAVA只有到岸价格,没有参照交货。 所谓参照传递,也就是传递了参照的副本,所以本质上也是按价传递。

二. JVM内存模型

三、数据是如何存储在内存中的我已经知道了。 Java的数据类型有基本的数据类型和引用数据类型,您使用什么策略来存储这些数据?

1 .基本数据类型存储:

a .基本数据类型的局部变量:

用于定义基本数据类型的局部变量和数据直接存储在内存中的堆栈(如上所述的“虚拟机堆栈”)中,而数据本身的值存储在堆栈区域中。 b .基本数据类型的成员变量:顾名思义,是在类中定义的变量。 class Person{ private int age; 私有字符串名称; 私有内等级; 5//settergetter方法static void run () system.out.println ) ' run…' ); (; } publicstaticvoidmain (字符串[ ] args ) { int age=50; int weight=50; int grade=6; int[] arr=new int[3]; 人员per=new person (; }

首先,JVM创建一个名为age的变量,并将其存储在局部变量表中。 然后去找堆栈里有没有字面大小为50的东西。 如果有,直接将age指向这个地址。 否则,JVM将在堆栈中创建用于存储“50”内容的空间,并将age指向此地址。 作为同一局部变量的per中,age、name、grade存储在堆内per对象的空间中。 因此,如果声明并初始化基本数据类型的局部变量,则变量名称和文字值将存储在堆栈中,并表明它们是实际内容。 基本数据类型的成员变量名称和值存储在堆中,并具有一致的生命周期和对象。

“int weight=50; 来看看”。 根据刚才的想法,堆栈中已经存在字面量为50的内容,所以weight直接指向了这个地址。 由此可见,堆栈中的数据由当前线程共享。

//重试权重=40; 如果在代码中再次为weight变量赋值,JVM将去堆栈中查找字面量为40的内容,如果发现没有,它将打开内存空间并存储40,然后将weight指向该地址。 由此可见:

基本数据类型的数据本身保持不变。 重新赋值局部变量时,在堆栈中重新查找现有的相同数据,而不是更改内存中的文字内容。 如果堆栈中不存在,则重新打开内存以保存新数据,并将对要重新赋值的局部变量的引用指向包含新数据的地址。

c .基本数据类型的静态变量:上述方法区域用于存储共享数据,因此基本数据类型的静态变量名称和值存储在方法区域的运行时常量池中,静态变量随类加载而加载,类消失时消失2 .引用数据类型的存储330

如上所述,堆用于存储对象本身和数组,而引用(句柄)存储实际内容的地址值。 因此,即使在上面的程序中运行图,定义对象也是可见的。

人员per=new person (; 正在运行人员人员; 时,JVM首先打开用于将per变量存储在虚拟机堆栈内的变量表中的内存。 运行per=new Person ()时,JVM会创建Person类的实例对象,打开用于在堆中存储此实例的内存,同时将实例的地址值分配给per变量。 因此,对于引用数据类型的对象/数组,可以看到变量名称位于堆栈中,变量值存储对象的地址,而不是对象的实际内容。

四.按值传递和按引用传递的按值传递:调用方法时,实参通过形参将其内容的副本传递到方法内部。 此时,形参收到的内容是实参值的复印件。 因此,对方法中形状引用的任何操作都只是对该副本的操作,而不影响原始值的内容。

将a和w作为实例传递给valueCrossTest后,可以看到无论在方法中执行什么操作,a和w最终都不会改变。

因为,首先程序运行时,会调用mian (方法。 此时,JVM为main ) )方法将堆栈帧(即当前堆栈帧,然后按main ) )中的本地变量表、操作堆栈和方法出口等信息存储在虚拟机堆栈中。 例如,a和w都是mian ) )方法中的局部变量

此外,当执行valueCrossTest ()方法时,JVM会在虚拟机堆栈中插入堆栈(即当前堆栈帧,valueCrossTest ) )中存储本地变量等信息。 因此,age和weight躺在包含valueCrossTest方法的堆栈框架上,其值从a开始

因此,可以对应a和age、w和weight的内容不一致,在方法内重新代入时:

也就是说,age和weight的更改只是更改了当前堆栈帧(valueCrossTest方法所在的堆栈帧)的内容,方法执行结束后,这些局部变量将被放弃,mian方法将存在因此,该值传递实际内容的副本,并传递给副本

的操作不影响原内容,也就是形参怎么变化,不会影响实参对应的内容。

引用传递:
”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向通愉快内存地址,对形参的操作会影响的真实内容。
定义对象:


结果:

person经过personCrossTest()方法的执行之后,内容发生了改变,这印证了上面所说的“引用传递”,对形参的操作,改变了实际对象的内容。
然而还没完,再看下面:

结果??

其实:不管是第一次还是第二次,无论是基本类型和是引用类型,在实参传入形参时,都是值传递,也就是说传递的都是一个副本,而不是内容本身。
第一次示意图:
第二次示意图:

由图可以看出,方法内的形参person和实参p并无实质关联,它只是由p处copy了一份指向对象的地址,此时:p和person都是指向同一个对象。因此在第一个例子中,对形参p的操作,会影响到实参对应的对象内容。而在第二个例子中,当执行到new Person()之后,JVM在堆内开辟一块空间存储新对象,并且把person改成指向新对象的地址,此时:p依旧是指向旧的对象,person指向新对象的地址。所以此时对person的操作,实际上是对新对象的操作,于实参p中对应的对象毫无关系。 五、总结

在Java中所有的参数传递,不管基本类型还是引用类型,都是值传递,或者说是副本传递。只是在传递过程中:
如果是对基本数据类型的数据进行操作,由于原始内容和副本都是存储实际值,并且是在不同的栈区,因此形参的操作,不影响原始内容。如果是对引用类型的数据进行操作,分两种情况,一种是形参和实参保持指向同一个对象地址,则形参的操作,会影响实参指向的对象的内容。一种是形参被改动指向新的对象地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。

本文大部分来自于大佬这篇文章

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。