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 中是怎么来操作的。

最新文章

  1. VMWare Tools 和 Shared folder(共享文件夹)
  2. Daily Scrum02 12.11
  3. 内存不足时,调用ajax报的错
  4. NK3C程序资源占用分析
  5. 思想&观点&人生
  6. 【jquery】基于 jquery 实现 ie 浏览器兼容 placeholder 效果
  7. c#获取网页内容的三种方法
  8. 关于Mac终端故障一直出现 [进程已完毕]
  9. ubuntu16编译安装mysql5.7
  10. Windows下为Lua脚本进行加密处理
  11. c/c++ 多线程 利用条件变量实现线程安全的队列
  12. Node.js 安装与管理
  13. linux 高级路由
  14. easyui 获取特定页签tab
  15. c# 除掉前三个字符,剩下的4个字符全为数字方为特殊车辆
  16. linux 下 安装nginx及压力测试
  17. jQuery的无new构建
  18. cf1060E. Sergey and Subway(树形dp)
  19. node.js3
  20. linux自定义开机启动服务和chkconfig使用方法

热门文章

  1. 彻底搞懂JVM类加载器:基本概念
  2. idea 2019 集成activiti, idea activiti 新建bpmn文件, 解决idea activiti中文乱码
  3. mapping 映射
  4. CentOS 8 安装
  5. MySql || 快速创建100w条记录
  6. 逆向破解之160个CrackMe —— 029
  7. 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)
  8. Module build failed: Error: Cannot find module 'node-sass'
  9. Hibernate框架学习2
  10. Android 开发基础入门篇: Android Studio 导入工程