一段代码看 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 ...
随机推荐
- URL&HTTP协议
一般来讲,URL地址有五个部分组成,协议,域名,端口,路径,URL地址参数,通常“//'之前的部分就是协议 常用的协议有: http 超文本传输协议 htttps http+ssl ssh 用来实现远 ...
- ubuntu 16.04 创建NFS
快速设置 安装NFS服务 sudo apt-get install nfs-kernel-server 编辑/etc/exports文件 vim /etc/exports /opt/nfs *(rw, ...
- Linux shell if条件判断1
shell 逻辑控制语句: 分支判断结构 if case 循环结构 for while unt ...
- The 2019 Asia Nanchang First Round Online Programming Contest E. Magic Master
题目链接:https://nanti.jisuanke.com/t/41352 题目意思还是好理解的,看过的人不多,感觉是被通过量吓到了.其实就是个水题,反向模拟就好了, 用队列模拟,反向模拟,它要放 ...
- java lambda表达式检查list集合是否存在某个值
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class ...
- Codeforces H. Kilani and the Game(多源BFS)
题目描述: Kilani and the Game time limit per test 2 seconds memory limit per test 256 megabytes input st ...
- Win10开启快速启动后关机变重启
同样可以用来解决,“msconfig引导为空”,“默认操作系统为空”,“win10改为uefi启动后关机变重启”,“legacy转uefi后无法关机” 问题起因 换完主板和cpu后,新的主板在开机时总 ...
- 在CentOS7.5上安装Docker,在Docker中拉取CentOS7.5镜像并安装SSH服务
# 安装docker yum install -y docker # 启动docker systemctl start docker # 加入开机启动 systemctl enable docker ...
- 字符串format()方法的基本使用
<模板字符串>.format(<逗号分隔的参数>) 其中,模板字符串是一个由字符串和槽组成的字符串,用来控制字符串和变量的显示效果.槽用大括号({})表示,对应format() ...
- 面向对象高级B(元类)
元类 python一切皆对象,类实际上也是一个一个对象 类是一个对象,那他一定是由一个类实例化得到,这个类就叫元类 如何找元类 class Person: def __init__(self, nam ...