Java值传递与引用传递
来源:互联网 发布:淘宝网柒牌男装 编辑:程序博客网 时间:2024/04/29 10:57
Jvm中堆与栈存储区别
Heap(堆)
Stack(栈)
JVM中的功能
内存数据区
内存指令区
存储数据
对象实例
基本数据类型,指令代码,常量,对象的引用地址
1, 保存对象实例,实际上保存的是对象实例的属性值,属性类型和对象本身的标记等,并不保存对象的方法(方法是指令,保存在stack中)。
对象实例在heap中分配好以后,需要在stack中保存一个4个字节的内存地址,用来定位该对象实例的在heap中的位置,以便于找到该对象的实例。
2, 基本数据类型包括,byte,short,int,long,double,float,char,Boolean.
Java的堆是一个运行时的数据区,类的对象从中分配空间。这些对象通过new,newarray,anewarray和multinewarray等指令建立,它们不需要程序代码来显示的释放。Heap是用垃圾回收器负责回收的,堆得优势可以动态的分配内存大小,生存期不必事先告诉编译器,因为他是运行时动态分配内存的,java的垃圾回收器会自动回收掉这些不再使用的数据。但缺点是由于是运行时动态分配,所以速度相对较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本的数据类型,byte,short,int,long,double,float,char,Boolean和对象句柄即应用。
可见垃圾回收器是针对堆得,而栈本身是first in,last out 先进后出,能够自动释放,这样就明白到new创建的,都是放到堆里面的。
在java里面参数传递都是按值传递 这句话的意思是:按值传递是传递的值得拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。
下面举三个例子
public class Test1 { public static void main(String[] args) { int n = 3; System.out.println("Before change, n = " + n); changeData(n); System.out.println("After changeData(n), n = " + n); } public static void changeData(int nn) { n = 10; }}
我想这个例子大家都明白,基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的,输出的结果证明了这一点:
Before change,n = 3
AfterchangeData(n), n = 3
我理解更简单,main函数中的实例n跟changeData函数中的形参是两个的实例,第一次打印的是实例n的原始值,第二次打印的依然是n的原始值,但是如果你在changeData中打印形参n的值却是10,改变的是main中实例n的原始值的拷贝。这样其实更有助于理解。
public class Test2 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb); changeData(sb); System.out.println("After changeData(n), sb = " + sb); } public static void changeData(StringBuffer strBuf) { strBuf.append("World!"); }}
先看输出结果:
Before change, sb = Hello
After changeData(n), sb = Hello World!
从结果来看,sb的值被改变了,那么是不是可以说:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。从上面例子的输出结果来看,这样解释是合理。
现在我们对上面的例子稍加改动一下
public class Test3 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb); changeData(sb); System.out.println("After changeData(n), sb = " + sb); } public static void changeData(StringBuffer strBuf) { strBuf = new StringBuffer("Hi "); strBuf.append("World!"); }}
按照上面例子的经验:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。你会认为应该输出:
Before change, sb = Hello
After changeData(n), sb = Hi World!
但运行一下这个程序,你会发现结果是这样的:
Before change, sb = Hello
After changeData(n), sb = Hello
这就是让人迷惑的地方,对象作为参数传递时,同样是在方法内改变了对象的值,为什么有的是改变了原对象的值,而有的并没有改变原对象的值呢?这时候究竟是“传值”还是“传引用”呢?
这两个方法是的实例是引用类型,引用类型中相对于基本类型要复杂一些。
Test2中main方法StringBuffer的实例sb是hello,sb是对象的引用。好的,那在changData中形参strBuf传参传的是引用sb,sb与strBuf共同持有一个引用,同时指向对象hello,因此在main和changeData中共同处理一个引用,进而改变了对象。
Test3中main方法StringBuffer的实例sb也是hello,但是在changeData中却new了一个对象strBuff,引用类型new对象肯定是在栈中重新开辟一块内存,而在堆里分配了hi这参数,因此在changeData中同理的又不是跟main中相同的引用。所以结果就是我们看到的。
当然string这个类型也比较特殊,对它的一些操作符是重载的,如:
String str = “Hello”; 等价于String str = new String(“Hello”);
String str = “Hello”;
str = str + “ world!”;等价于str = new String((newStringBuffer(str)).append(“ world!”));
- java值传递与引用传递
- java值传递与引用传递
- Java值传递与引用传递
- java 引用传递与值传递
- Java中的值传递与引用传递
- java中的值传递与引用传递
- java值传递与引用传递
- JAVA 值传递与引用传递详解
- Java值传递与引用传递
- Java 值传递与引用传递
- Java值传递与引用传递
- Java值传递与引用传递
- java中的值传递与引用传递
- Java值传递与引用传递
- Java 值传递与引用传递
- Java的值传递与引用传递
- Java中的值传递与引用传递
- java的值传递与引用传递
- Android Activity生命周期
- hostname的一些记录
- Java算法---遗传算法示例
- Swift - 打开第三方应用,并传递参数(附常用App的URL Scheme)
- EL表达式与JSTL(为空判断)
- Java值传递与引用传递
- nodejs操作mysql数据库
- oracle 关于with admin option和with grant option说明
- 谈谈 Memcached LRU
- VTK里面三维文本显示
- iOS 多线程开发(二)
- PHP iconv()函数转字符编码的问题
- 关于内部类的总结
- MATLAB函数大全