一段代码看 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 ...
随机推荐
- 第一部分day2-for、while、数据类型(字符串、列表、元组)
数据类型 数据类型的初识 1.数字 整数 int (integer) 整型 (注:python3 不区分整型和长整型,统一称之为整型) 长整型 float(浮点型) complex(复数) 是由实数和 ...
- https工具类
import org.apache.commons.lang.StringUtils; import javax.net.ssl.*; import java.io.*; import java.ne ...
- django项目中的ajax分页和条件查询。
1,路由 #主页面路由 re_path('article/article_list/', article.article_list,name='article/article_list/'), #分页 ...
- dapi 基于Django的轻量级测试平台七 怎样部署到生产环境
QQ群: GitHub:https://github.com/yjlch1016/dapi Nginx+uWSGI 前置条件:以下所有操作均在root账号下面进行如果不是root用户请注意权限问题因为 ...
- DVWA之命令执行
一.命令执行漏洞 命令执行漏洞是指可以随意执行系统命令,属于高危漏洞之一,也属与代码执行范围内,好比说一句话木马<?php@eval($_POST['cmd']);?> 二.分类: 1.代 ...
- 如何使用和关闭onbeforeunload 默认的浏览器弹窗事件
Onunload,onbeforeunload都是在刷新或关闭时调用,可以在<script>脚本中通过 window.onunload来指定或者在<body>里指定.区别在于o ...
- 日志级别facility
0 EMERG(紧急) 会导致主机系统不可用的情况 1 ALERT(警告) 必须马上采取措施解决的问题 2 CRIT(严重) 比较严重的情况 3 ERR(错误) 运行出现错误 4 WARNING(提醒 ...
- postgres9.5.3升级postgres11.6
附上postgres下载地址: https://yum.postgresql.org/11/redhat/rhel-7-x86_64/repoview/postgresqldbserver11.gro ...
- hbase运行原理
HBase特点 1)海量存储 Hbase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据.这与Hbase的极易扩展性息息相关.正式因为Hbase良好 ...
- [Algorithm] 118. Pascal's Triangle
Given a non-negative integer numRows, generate the first numRows of Pascal's triangle. In Pascal's t ...