java的引用与指针有什么关系?实例代码展示

BSO 2020-09-07 15:52:47 java常见问答 8170

上次我们已经介绍过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();
        a = a.add0(ex); //等价于a.add0(ex),无需返回值,因为通过传递的对象地址(句柄),直接修改了ex中i的值
        a.add1(ex); //add0,add1都在其中的方法体中直接修改了ex.i的值,因此add0的返回值有点多余
        a.modify0(ex); //对ex所产生的影响同add1
        a.modify1(ex); //对ex没有产生任何影响(而且这就是等价于什么也没有做).
        //这可能会让一部分人搞不清了。为什么呢?因为是对象地址的副本"值传递",在modify1中e=new Example();实际上e仅仅是保存ex对象地址的副本的一个句柄,当对e赋值时仅仅是对堆栈中e的赋值(对ex指针副本的变量e赋值),而并没有改变ex的句柄的指向,当方法调用完毕堆栈弹出,e就将要被垃圾回收,没有任何用处。当然你可以将它作为返回值,这就是另外一回事了。
    }
}

以上就是关于java的引用与指针之间的关系的详细解析,并且通过实际的代码为大家展示。想要了解更多java经典例子常见问题,敬请关注奇Q工具网。

推荐阅读:

java对象类型转换,强制对象类型转换介绍

java对象类型转换实例分享

java对象类型转换,向上转型和向下转型详细介绍