一段代码看 Java 引用类型

时间:2019-06-12
本文章向大家介绍一段代码看 Java 引用类型,主要包括一段代码看 Java 引用类型使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Java 中的变量类型分为值类型和引用类型:

值类型就是基本类型的变量,如 char, int, float, double...

引用类型包括了数组,以及其它所有用 class 定义的数据类型。

虽然 Java 中一切都是类,但是对于值类型,因为不需要存储其‘对象’特征,所以,编译器只为他们分配了 stack 上的空间,存储单个的值就可以了。而引用类型则不同,他们的变量存储分为两部分:在 stack 中的引用(指针),以及在 heap 中的对象实例。大概长这样(图借别人的,看最后的链接):

使用下面一段代码来理解这个问题,以及怎样避免这个问题带来的性能损耗(String.equals() 的标准实现)。

 1 public boolean equals(Object anObject) {
 2         if (this == anObject) {
 3             return true;
 4         }
 5         if (anObject instanceof String) {
 6             String anotherString = (String)anObject;
 7             int n = value.length;
 8             if (n == anotherString.value.length) {
 9                 char v1[] = value;
10                 char v2[] = anotherString.value;
11                 int i = 0;
12                 while (n-- != 0) {
13                     if (v1[i] != v2[i])
14                         return false;
15                     i++;
16                 }
17                 return true;
18             }
19         }
20         return false;
21     }

 一起从这段代码来看看值类型和引用类型的区别:

1. 第 2 行,首先使用 == 判断,两个引用指向的是否为同一个对象实例。

2. 第 5 行,判断传入的 object 是否为同一个,即他们是不是指向同一个“对象实例”的两个“对象引用”。

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 对象的比较,显然是要耗费更多资源的...)。

关于数组

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

原文地址:https://www.cnblogs.com/pied/p/11008779.html