这篇博文主要介绍Java 对象的引用方式,以及对于Java 程序设计语言中关于”引用传递”与”值传递”问题谈一谈看法。

Java对象的访问定位

我们知道Java 程序需要通过栈上的引用(reference) 数据来操作堆上的具体对象。由于reference 类型在Java 虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用通过何种方式去定位、访问堆中对象的具体位置,所以对象的访问方式也是取决于虚拟机而定的。但是主流的访问方式有句柄和直接指针两种。下面一一分作介绍。

句柄访问

使用句柄方式访问的话,在Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。如图:

直接指针

如果使用直接指针访问,那么Java 堆中对象的布局就必须考虑如何放置访问类型数据的想关信息,而reference 中存储的直接就是对象的地址。如图:

两种方式的对比:
    使用句柄的最大好处就是reference 中存储的是稳定的句柄地址,在对象移动(在垃圾回收时往往存在大量的对象移动)时只会改变句柄中的实例数据指针,而reference 本身不需要修改。
    使用直接指针的最大好处时速度更快,它节省了一次指针定位的开销,由于对象的访问在Java 中非常普遍,因此这类开销积少成多后也是一项非常可观的执行成本。就Sun HotSpot 虚拟机而言,它是使用第二种方式进行对象访问的。

下面就来谈一谈Java 中关于“引用传递”与“值传递”的问题:

在探讨这个问题之前我们先了解一下什么是值传递什么是引用传递(来自百度百科):
    引用传递:所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
    值传递:值传递是在程序设计中,对于函数调用的一种方法,值引用只是把值传递到新的变量,修改新的变量,不会修改原来的参数。

通过上面关于Java 对象的两种访问方式我们知道,在虚拟机栈中通过对象的引用来操作堆上的具体对象。下面来看两段代码:

    @Testpublic void test1(){int i = 5;change1(i);System.out.print(i);}public void change1(int i){i = 10;}

我想大多数Java 程序员都是到输出的结果是5,还有下面一段代码:

    @Testpublic void test2(){Demo demo = new Demo();System.out.println(demo.num);change2(demo);System.out.println(demo.num);}public void change2(Demo demo){demo.num = 10;}class Demo{public int num = 5;}

输出结果为:
5
10

上面两个例子分别测试了基本数据类型与引用数据类型,现在就上面出现的结果做一些理论上的分析:
    基本数据类型的传递:基本数据类型的值就保存在变量中,传递的是基本类型的字面量值的拷贝,当发生传递时并不会改变原来的变量值。
    引用数据类型的传递:变量中保存的是实际对象的地址,传递的是堆中对象的一个拷贝(也就是引用),操作的并不是堆中的对象本身,在数据传递时原来的引用地址会被覆盖,赋值运算会改变原来引用中保存的地址,但是堆中的对象本身不会被改变


总结:
    “Java 所支持的‘按址传递’传递是完全错误的”,因为Java 对象标志符实际上是“符号引用”。也许有人会赞成这种精确却令人费解的解释,但我认为我的这种方法可以简化概念上的理解并且不会伤害到任何事物。(好了,那些言语专家可能会说我在说谎,但是我认为我只是提供了一个合适的抽象罢了。
                                                                                                                             ->《Java编程思想》

参考资料:《深入理解Java 虚拟机》周志明 著
                                                                                                                   《Java 编程思想》Bruce Eckel 著
                                                                                                                     知乎平台->手动@ Intopass、祖春雷
                                                                                                                     百度百科

Java对象的访问定位相关推荐

  1. java对象的访问定位_2、JVM-Java对象的创建、对象结构、对象访问定位-Go语言中文社区...

    目录 记录下来方便个人学习复习 注:根据new的参数在常量池中定位一个类的符号引用 --这句话的意思是:常量池相当于c语言中的指针地址集合,所以就是在常量池中保存new对象的地址,通过地址定位对象在堆 ...

  2. java对象的访问定位_JVM创建对象及访问定位过程详解

    1.对象的创建 虚拟机接收到new指令时,检查这个指令能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化.如果都没有,先执行类加载过程. 在类加载通过后,虚拟 ...

  3. java对象的访问定位_深入理解java虚拟机---对象的访问定位(十)

    引用其他人的文章: https://www.cnblogs.com/YYfish/p/6722258.html 那是怎么访问对象呢? java 程序是通过栈上的reference数据来操作堆上的具体对 ...

  4. Java面试题:synchronized和对象的访问定位的两种方式

    说一说自己对于 synchronized 关键字的理解 ? synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者 代码块在任意时 ...

  5. Java常见面试题:对象的访问定位的两种方式

    对象的访问定位的两种方式 java对象在访问的时候,我们需要通过java虚拟机栈的reference类型的数据去操作具体的对象. 由于reference类型在java虚拟机规范中只规定了一个对象的引用 ...

  6. 对象创建方法,对象的内存分配,对象的访问定位

    对象创建方法: JVM遇到一条new指令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.连接和初始化过. 如果没有,那必须先执行相应的类的加 ...

  7. JVM(三)——对象的访问定位

    JVM(三)--对象的访问定位 创建完对象,到了使用对象的时候,通常声明一个同类型的引用指向该类型的对象,由这个引用来操作对象的字段.方法等. Object obj = new Object();复制 ...

  8. Java对象的创建、内存布局和访问定位

    在Java运行时数据区中,我们知道了虚拟机内存的概况,本文介绍虚拟机内存中的数据的其它细节,如对象如何创建.如何布局以及如何访问. 基于实用的原则,这里以HotSpot虚拟机和常用的内存区域Java堆 ...

  9. java 句柄池_深入理解JVM之Java对象的创建、内存布局、访问定位详解

    本文实例讲述了深入理解JVM之Java对象的创建.内存布局.访问定位.分享给大家供大家参考,具体如下: 对象的创建 一个简单的创建对象语句Clazz instance = new Clazz();包含 ...

最新文章

  1. HDU OJ 5437 Alisha’s Party 2015online A
  2. 【C 语言】编译过程 分析 ( 预处理 | 编译 | 汇编 | 链接 | 宏定义 | 条件编译 | 编译器指示字 )
  3. c++中虚函数和纯虚函数定义
  4. Shoutem旨在成为React Native移动应用领域的WordPress
  5. P3648-[APIO2014]序列分割【斜率优化】
  6. php mysql html标签_HTML标签格式化PHP和MySQL
  7. 特斯拉 神经网络计算机,特斯拉即将推出神经网络计算机 或大幅提升Autopilot性能...
  8. 【树莓派】Linux指令使用记录
  9. 微信小程序 webview 传递URL中含有特殊字符-,=
  10. 将Excel的数据导入DataGridView中[原创]
  11. 【致远FAQ】致远OA启动不起来了(下集)
  12. Element表格序号问题
  13. 安装ADOBE READER时无法将数值写入键
  14. 安全研究 # 二进制代码相似性检测综述
  15. 鸡脚蹬子生长秘籍 鸡脚蹬子短是缺乏什么营养
  16. openwt dns 解析部分域名出错问题。
  17. mysql隔离级别到底是什么
  18. 软件测试工程师-面试如何使用代码进行接口测试?
  19. 使用git命令——分支切换
  20. C51单片机程序注释与样例

热门文章

  1. classpath和读取resources目录下的文件
  2. 根据省市区查询对应权限下的数据
  3. Visual C++——定时刷新重绘窗口[WM_PAINT消息]解决方案
  4. 解析ASP网页的执行顺序
  5. 计算机网络(谢希仁第八版)第二章:物理层
  6. 计算机机房坏境设施演练,计算机机房环境设施应急演练方案
  7. ubuntu中文文件名乱码
  8. Android Studio 插件开发详解四:填坑
  9. Redis Lua脚本实现原子性操作
  10. 关于Crypto.PublicKey.RSA,在generate后无法被赋值问题