程序员的中年危机,Java句柄与指针


句柄:一个唯一的整数,作为对象的身份id,区分不同的对象,和同类中的不同实例。程序可以通过句柄访问对象的部分信息。句柄不代表对象的内存地址。在Java中的任何东西都可以看做对象,存在一种标识符实际指向一个对象的句柄.在Java的其他地方或者数据中也有称为 "引用"或者 “指针”. 只是一个引用地址,我们不能认为Java中没有指针,其实这就是一个指针,我们每次操作对象就是根据句柄去找到对象操作对象的. 即使没有对象,我们也可以让句柄单独存在。

可以将句柄简单的理解为对象的引用.

举一个例子:


Vehicle ve = new Vehicle();

通常把这条语句的动作称之为创建一个对象,其实,它包含了四个动作。

  1. 右边的“new Vehicle”,是以Vehicle类为模板,在堆空间里创建一个Vehicle类对象(也简称为Vehicle对象)。

  2. 末尾的()意味着,在对象创建后,立即调用Vehicle类的构造函数,对刚生成的对象进行初始化。构造函数是肯定有的。如果你没写,Java会给你补上一个默认的构造函数。

  3. 左边的“Vehicle veh 1”创建了一个Vehicle类引用变量。所谓Vehicle类引用,就是以后可以用来指向Vehicle对象的对象引用。

  4. "="操作符使对象引用指向刚创建的那个Vehicle对象。

我们可以把这条语句拆成两部分:


Vehicle ve;

ve = new Vehicle();

效果是一样的。这样写,就比较清楚了,有两个实体:一是对象引用变量,一是对象本身。

一个Vehicle类可以据此创建出无数个对象,这些对象不可能全叫“Vehicle”。对象连名都没有,没法直接访问它。我们只能通过对象引用来间接访问对象。Java中就是用句柄来标识每一个对象的.

如何更好的理解句柄呢?我们再举一个例子:


Person person;

person = new Person("张三");

person = new Person("李四");

刚开始我们分配了一个句柄,它没有连接到任何对象,它就是null。在第二行,我们new了一个叫“张三”的person,将person指向“张三”这个对象,然后又指向了“李四”这个对象。也就是说,Person person,这句话只是声明了一个Person类的引用,它可以指向任何Person类的实例。

二、对象访问句柄


由于reference类型在Java虚拟机规范里只规定了一个指向对象的引用,并没有定义这个引用应该通过哪种方式去定位,以及访问到Java堆中的对象的具体位置,因此不同虚拟机实现的对象访问方式会有所不同,主流的访问方式有两种:使用句柄和直接指针。

使用句柄访问方式

如果使用句柄访问方式,Java堆中会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。使用句柄方式最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。

三、使用直接指针访问方式


如果使用该方式,Java堆对象的布局就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址。使用直接指针方式最大的好处就是速度更快,他节省了一次指针定位的时间开销。

就HotSpot而言,他使用的是直接指针访问方式进行对象访问,但从整个软件开发的范围来看,各种语言和框架使用句柄来访问的情况也十分常见。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值