0.前言
谈到传递,先说一下
函数参数传递
形参:定义方法时写的参数
实参:调用方法时传递的具体参数
(参数传递本质上都是值传递)
之后说一下java中的
数据类型
基本数据类型
整形 byte(8位 1字节 -128~127)short (16位 2字节 -32768~32767) int(32位 4字节-2^31-1~2^31) long(64位 8字节 -2^63-1~2^63 需要在后面加L或l)
浮点型 float (32位 4字节 1位符号位 8位指数 23位有效位数 需要加F或f后缀) double(64位 8字节 1位符号位 11位指数位 52位有效尾数) 浮点数不可以精确计数
字符型 char(16位 2字节)Unicode表示
布尔型 Boolean (true false)
引用数据类型
对象Object
数组Array
接口Interface
1.值传递传递的主要就是就是基本数据类型
传递的是值的拷贝(将实参的内容copy一份给形参)
可以这么形容
- 虚拟机分配给s(实参)一个内存地址,并且存了一个默认值(比如0).
- 虚拟机复制了一个s,我们叫他s',s’和s的内存地址不同,但存的值都是默认值。
- 虚拟机讲s’传入方法,方法将s’的值改为1.
- 方法结束,方法外打印s的值,由于s内存中的值没有改变,还是默认值,所以打印是默认值.
- 这个s‘扮演了一个方法内临时变量的作用(会被垃圾回收)
2.引用传递传递的主要就是就是引用类型
传递的实质上是该类型所在的地址(将实参的地址值copy一份给形参)
可以这么形容
- 虚拟机在堆中开辟了一个引用类型p的内存空间,内存中包含p的初始内容(比如p0)。
- 虚拟机在栈中分配给m一个内存地址,这个地址中存的是1中的p的内存地址。(举例Class m=new p();)
- 虚拟机复制了一个m,我们叫他m’,m和m’的内存地址不同,但它们存的值是相同的,都是1中p的内存地址。
- 将m’传入方法,方法改变了1中的p0。
- 方法结束,方法外打印m中变量的值,由于m和m’中存的都是1中p的地址,但是1中p里的值发生了改变, 所以,方法外打印m的值,是方法执行以后的。我们看到的效果是封装类型的值是改变的。
3.特殊的String StringBuffer StringBuilder以及一些包装类Integer Double之类的
3.1 String(表现为值传递,即方法内的修改不影响方法外的值)
- 虚拟机在堆中开辟一块内存,并存值”ab”。
- 虚拟机在栈中分配给str一个内存,内存中存的是1中的地址。
- 虚拟机复制一份str,我们叫str’,str和str’内存不同,但存的值都是1的地址。
- 将str’传入方法体
- 方法体在堆中开辟一块内存,并存值”cd”
- 方法体将str’的值改变,存入5的内存地址
- 方法结束,方法外打印str,由于str存的是1的地址,所有打印结果是”ab”
这里说明一下String类是final类内容不可修改,具体到底层实现就可以看出,实际上它的subString, concat ,repalce方法实际上是执行了
char data[] = {'a', 'b', 'c'};
String str = new String(data);
意思是新创建了一个String, 将新的地址值赋值给str‘(就是改变了形参指向的对象),实际上实参的内容没有变
3.2 Integer,Double等包装类(表现为值传递,即方法内的修改不影响方法外的值)
也可以理解为改变了形参指向的对象,修改的是新对象的值,实际上实参指向的对象内的值没有变
3.3StringBuffer和StringBuilder(表现为引用传递,方法内的修改会对方法外产生影响)
值可变,形参指向的就是具体的值,没有改变指向
(部分应用自https://www.cnblogs.com/boboooo/p/9066831.html)
(深入理解java中的String 对String问题比较透彻https://www.cnblogs.com/xiaoxi/p/6036701.html)