一段代码看 Java 引用类型
Java 中的操作数(不知道叫什么,相对于 bytecode 而言,类似 CPU 的操作码和操作数)分为值类型和引用类型:
值类型就是直接存储最终数值的,如 char, int, float, double...
引用类型包括了数组,以及其它所有用 class 定义的数据类型,这种数据类型由引用和对象实例连部分组成。
虽然 Java 中一切都是类,但是对于值类型,因为不需要存储其‘对象’特征,所以,编译器只为他们分配了 stack 上的空间,存储单个的值就可以了。而引用类型则不同,他们的变量存储分为两部分:在 stack 中的引用(指针),以及在 heap 中的对象实例。大概长这样(图借别人的,看最后的链接):

使用下面一段代码来理解这个问题,体会下区别(String.equals() 的标准实现)。
 public boolean equals(Object anObject) {
         if (this == anObject) {
             return true;
         }
         if (anObject instanceof String) {
             String anotherString = (String)anObject;
             int n = value.length;
             if (n == anotherString.value.length) {
                 char v1[] = value;
                 char v2[] = anotherString.value;
                 int i = 0;
                 while (n-- != 0) {
                     if (v1[i] != v2[i])
                         return false;
                     i++;
                 }
                 return true;
             }
         }
         return false;
     }
一起从这段代码来看看值类型和引用类型的区别:
1. 第 2 行,首先使用 == 判断,两个引用指向的是否为同一个对象实例。
2. 第 5 行,判断传入的 object 是否是 String 的实例。
3. 第 6 行,将传入的 object 强制转换为 String 类。
4. 第 7、8 行,取 this.value.length 与 anotherString.value.length 作比较。value 的类型是 char[],因为数组是一个有限的数据集合,其定义时就已经固定了长度。所以这个操作被编译后,只是两个内存单元的内容比较。
5. 第 9、10 行,创建新的数组引用,分别指向 this.value 和 anotherString.value。
6. 第 11-16 行,逐个比较两个 char 数组中的元素。直接比较两个数组各个元素的效率,是要比比较 String 元素的效率更高的(转化为 Char 对象的比较,再比较 Char value,显然是要耗费更多资源的...)。
关于数组
数组是 JVM 提供的基本数据类型之一。
JVM 直接提供的数组类型有 T_BOOLEAN([Z, 1byte)、T_CHAR([C, 2bytes)、T_FLOAT([F, 4bytes)、T_DOUBLE([D,8bytes)、T_BYTE([B, 1bytes)、T_SHORT([S, 2bytes)、T_INT([I, 4bytes)、T_LONG([J, 8bytes)。
我们可以轻松验证,一个数组是 instanceof Object,同时,数组调用方法 getClass().getName(),也是可以正确输出的。
public class arrayTest {
    public static void main(String[] args) {
        int[] a = {1,2,3,4};
        System.out.println(a.getClass().getName());
        System.out.println("a is instanceof Object? "+(a instanceof Object));
    }
}
当然,数组的实现方法是在 JVM 中的,但这并不妨碍我们像使用其它类/对象一样类使用数组。
一个 array 在内存中的 layout 大概长这样:

从上面的图中,可以看到两个信息,第一个,数组在内存中是连续存放的,第二个,header 之后的位置存储着数组的长度。这也是为什么我们可以直接获取数组的 length 属性,而其它一些类,必须使用 length() 方法。
关于 length 存储空间的大小,这个显示是和 JVM 实现有关的。查阅文档发现,sun 的 JVM (java7) 版本:32位系统中 size_t 是4字节的,在64位系统中,size_t 是8字节的。
另外,好奇对象数组是怎样存的,打印了一下 String[] b 的 classNage,显示是“[Ljava.lang.String;”。其中 “[” 表示这是个数组,“L/java/lang.String;” 叫做 JavaNative Interface Field Descriptors,大概就是说这是个 String 类型的数组了。
创建数组的 bytecode 是 JAVA_NEWARRAY 和 JAVA_ANEWARRAY,暂作记录,改天有空再看看 JVM 中是怎么来操作的。
一段代码看 Java 引用类型的更多相关文章
- 从一段代码看fork()函数及其引发的竞争
		首先来看一段从<UNIX环境高级编程>中摘录的一段很有意思的代码.借此我们再来谈谈fork()函数的一些问题. #include "apue.h" static voi ... 
- 一段代码了解Java中char和int的转换
		题目要求: 将输入的大写字母转成对应小写的后5个,如A转换后为f:如果转换后大于z则从a重新计,即多出1就转成a,多出2就转成b以此类推. Java代码: ```java private static ... 
- c#代码 天气接口  一分钟搞懂你的博客为什么没人看  看完python这段爬虫代码,java流泪了c#沉默了  图片二进制转换与存入数据库相关  C#7.0--引用返回值和引用局部变量  JS直接调用C#后台方法(ajax调用)  Linq To Json  SqlServer 递归查询
		天气预报的程序.程序并不难. 看到这个需求第一个想法就是只要找到合适天气预报接口一切都是小意思,说干就干,立马跟学生沟通价格.  不过谈报价的过程中,差点没让我一口老血喷键盘上,话说我们程序猿的人 ... 
- java中 synchronized 的使用,确保异步执行某一段代码。
		最近看了个有关访问网络url和下载的例子,里面有几个synchronized的地方,系统学习下,以下内容很重要,记下来. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一 ... 
- 从JVM的角度看JAVA代码--代码优化
		从JVM的角度看JAVA代码–代码优化 从JVM的角度看JAVA代码代码优化 片段一反复计算 片段二反复比較 在JVM载入优化为class文件,运行class文件时,会有JIT(Just-In-Tim ... 
- 127个常用的JS代码片段,每段代码花30秒就能看懂(上)
		127个常用的JS代码片段,每段代码花30秒就能看懂(上) JavaScript 是目前最流行的编程语言之一,正如大多数人所说:“如果你想学一门编程语言,请学JavaScript.” FreeCode ... 
- 编写高质量代码:改善Java程序的151个建议(第8章:异常___建议114~117)
		建议114:不要在构造函数中抛出异常 Java异常的机制有三种: Error类及其子类表示的是错误,它是不需要程序员处理也不能处理的异常,比如VirtualMachineError虚拟机错误,Thre ... 
- 编写高质量代码:改善Java程序的151个建议(第6章:枚举和注解___建议88~92)
		建议88:用枚举实现工厂方法模式更简洁 工厂方法模式(Factory Method Pattern)是" 创建对象的接口,让子类决定实例化哪一个类,并使一个类的实例化延迟到其它子类" ... 
- 编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议47~51)
		建议47:在equals中使用getClass进行类型判断 本节我们继续讨论覆写equals的问题,这次我们编写一个员工Employee类继承Person类,这很正常,员工也是人嘛,而且在JavaBe ... 
随机推荐
- Nginx 高级配置-状态页配置
			Nginx 高级配置-状态页配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 建议将nginx的监控状态的值通过zabbix或者Open-Falcon之类的监控工具来监控状态,并 ... 
- linux常见性能分析工具
			vmstat sar (来源于sysstat工具包,需要yum sysstat)iostat (来源于sysstat工具包,需要yum sysstat)free -muptimene ... 
- LVS (Linux虚拟服务器)模型及算法
			LVS(Linux Virtual Server)Linux虚拟服务器 LVS集群采用IP负载均衡技术和基于内容请求分发技术. 用户请求发给负载均衡调度器,由负载均衡调度器根据设定的调度算法将请求发给 ... 
- 盛科(Centec)交换机 SmartConfig 特性
			参考 DHCP manual pages DHCP option-66 & option-150 的区别 一. 原理 目前市场上稍微有些实力的交换机厂商,均支持自动化的批量开局部署,虽然具体实 ... 
- hexo 搜索功能
			搜索功能真心好用,当文章多起来的时候,标签提供的作用已经很少了,只能简单索引,搜索却能精确查找,这里我用的依旧是最简单的本地站内搜索. 安装插件 npm install hexo-generator- ... 
- uboot向kernel的传参机制——bootm与tags
			http://blog.csdn.net/skyflying2012/article/details/35787971 最近阅读代码学习了uboot boot kernel的过程以及uboot如何传参 ... 
- 14-C#笔记-字符串
			1. 基本操作 using System; namespace StringApplication { class Program { static void Main(string[] args) ... 
- LeetCode 1146. Snapshot Array
			原题链接在这里:https://leetcode.com/problems/snapshot-array/ 题目: Implement a SnapshotArray that supports th ... 
- 无旋treap大法好
			无旋Treap大法好 原理? 是一棵二叉查找树: 一个节点左子树权值都比他小,右子树权值都比他大 所以可以维护序列(以位置为权值),或数值(以数值为权值) 是一个堆: 每个节点除了上述提到的权值外,还 ... 
- Oracle客户端和服务端菜单区别
