静态类型和实际类型
静态类型是指变量最初被定义时的类型,而实际类型则是指变量所引用的对象的类型。当变量指向一个子类对象时,就有了多态的能力。
比如,我们有一个 Food 类和一个 Fruit 类,Fruit 继承自 Food。通过使用 Food 类型的变量来引用一个 Fruit 对象,我们可以实现多态。
Food food = new Fruit();
变量 food 的静态类型是 Food,但是它实际引用了一个 Fruit 对象。这意味着尽管 food 的外表是 Food 类型,但它能够调用 Fruit 类中的方法。
在 food 背后,有一个与它对应的 klass 对象,它记录了 food 的类型信息,就像是有一个标签写着 food 的品类和特点。每个 klass 对象维护着一个虚函数表,记录了类中所有的虚函数以及对应的指针。当 food 调用一个方法时,JVM 根据它的实际类型找到它的 klass 对象,然后在虚函数表中寻找正确的函数指针,使得 food 能够调用正确的方法。这种实现方式让我们具备了多态性,让它的行为可以根据实际情况进行适应。
生存空间
在 Java 中,变量的创建位置有三个:栈上、堆中和方法区中。变量的生命周期不同,所以它们会被创建在不同的位置。
首先,栈上的变量是局部变量,包括方法中定义的变量和代码块中定义的变量。它们的生命周期与方法调用或代码块的执行周期相同。变量在栈上的创建非常快速,而且在方法或代码块执行结束后会自动销毁。在使用栈上的变量之前,必须显式地为其赋值。
接下来,堆中的变量是通过 new 关键字创建的对象和数组。它们的生命周期与对象或数组本身相同,当没有引用指向它们时,会被垃圾收集器回收。堆中的变量创建比较耗时,需要为对象或数组分配内存空间,并进行初始化。在对象创建时,成员变量会被赋予默认值。
最后,方法区中的变量主要是静态变量。它们的生命周期与类的生命周期相同,在类被加载时创建,在类被卸载时销毁。静态变量在方法区中创建并初始化,在使用之前已经具有默认值。
引用类型
强引用(Strong Reference)
强引用是最常见的引用类型,它的作用是让对象存活期与引用的存活期保持一致。只要存在强引用指向一个对象,无论 JVM 内存是否充足,该对象都不会被回收。在上面的代码中,food 就是一个强引用,只要 food 存在,所指向的 Fruit 对象就不会被回收。
软引用(Soft Reference)
软引用是一种比较灵活的引用类型,它的作用是描述非必要对象。当 JVM 内存即将耗尽,也就是说 OOM 之前,垃圾回收器会将软引用对象列为可回收的对象范围,为程序提供更多可用空间。在实际应用中,软引用常用于缓存机制中,用来缓存一些大对象或者需要频繁创建销毁的对象。如果在代码中使用软引用,可以使用 SoftReference 类进行封装和管理。
弱引用(Weak Reference)
弱引用是相对于强引用的一种引用类型,强度较弱。如果一个对象只存在弱引用,且不存在强引用或软引用指向它,垃圾回收器在下一次进行垃圾回收时就会回收它。弱引用主要用于描述一些不是必需的对象,在强引用断开后该引用将不再持有对象。如果在代码中使用弱引用,可以使用 WeakReference 类进行封装和管理。
弱引用(Weak Reference)
弱引用是相对于强引用的一种引用类型,强度较弱。如果一个对象只存在弱引用,且不存在强引用或软引用指向它,垃圾回收器在下一次进行垃圾回收时就会回收它。弱引用主要用于描述一些不是必需的对象,在强引用断开后该引用将不再持有对象。如果在代码中使用弱引用,可以使用 WeakReference 类进行封装和管理。
此文章为10月Day8学习笔记,内容来源于极客时间《云时代JVM实战 》,强烈推荐该课程