Java中的引⽤和指针
java中内存的分配⽅式有两种,⼀种是在堆中分配,⼀种是在堆栈中分配,所有new出来的对象都是在堆中分配的,函数中参数的传递是在栈中分配的。通常情况下堆的内存可
以很⼤,⽐如32位操作系统中的虚拟内存都可以被堆所使⽤(当内存紧张的时候甚⾄硬盘都可以是堆的存储空间),⽽堆栈的内存分配是有限的。
这和c++中内存分配差不多。java中有⼏种基本类型如int,float,double,char,byte等,他们不是对象,除此之外⼀切都是对象,所有的对象都是在堆上分配的。但好像在C#中这些
都有封装好的⼀些⽅法,应该算是对象。
java中对象数组是什么,和c++类似,是句柄数组或者叫指针数组,⾥⾯保存的是每个元素的地址。和c++中不同,java没有操作符重载和拷贝构造函数(如果不了解这些也没有
关系),因此当创建对象或者对已经创建的对象赋值时(注意是对象,不是基本类型):Object a=new Object 和Object a=b(b是Object的⼦类型或者同类型)时,进⾏的是对
象地址的传递并复制。这就是所说的句柄的传递和赋值。
句柄⾥存储的就是对象的地址,句柄就是指针,只不过是你⽆法得到的地址,java就是通过这⼀点巧妙的将指针隐藏起来。当对象作为参数传递到⽅法中时,传递的就是对象的地
址,⽽⾏参中保存的是实参地址的副本(这就是最关键的地⽅,也是值传递,值传递就是将实参的值的副本作为⾏参)
如:
public class Example{
int i=0;
}
public class A{
public int i=0;
public Example add0(Example e){
e.i++;
return e;
}
public void add1(Example e){
e.i++;
}
public void modify0(Example e){
Example b=e;//将e⾏参对象的地址赋给句柄b
b.i++;//也同时修改了e.i和实参的值
}
public void modify1(Example e){
e=new Example();
e.i++;
}
public static void main(String[] args){
Example ex=new Example();
A a=new A();
java重载a=a.add0(ex);//等价于a.add0(ex),⽆需返回值,因为通过传递的对象地址(句柄),直接修改了ex中i的值
a.add1(ex);//add0,add1都在其中的⽅法体中直接修改了ex.i的值,因此add0的返回值有点多余
//这可能会让⼀部分⼈搞不清了。为什么呢?因为是对象地址的副本"值传递",在modify1中e=new Example();实际上e仅仅是保存ex对象地址的副本的⼀个句柄,当对e赋值时仅仅是对堆栈中e的赋值(
对ex指针副本的变量e赋值),⽽并没有改变ex的}
}
如果你能明⽩这个原理,可以避免⼀些潜在的逻辑错误,如:对象在⽅法中被改动了,记住c++在这⼀点上和java有很⼤的不同,c++默认的是值传递,⾏参会按照位复制实参
(如果⽤指针或者引⽤就和java很类似了),在⽅法中作为参数传递对象,java更象是c++中传递引⽤,当然还是有区别的,那就是c++中对象的引⽤不可再赋值为另⼀个对象。
本⽂为转载!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论