初始化

对象初始化

假设存在Dog类

  1. 即使没有显式地使用 static 关键字,构造器实际上也是静态方法。所以,当首次创建 Dog 类型的对象或是首次访问 Dog 类的静态方法或属性时,Java 解释器必须在类路径中查找,以定位 Dog.class。
  2. 当加载完 Dog.class 后(后面会学到,这将创建一个 Class 对象),有关静态初始化的所有动作都会执行。因此,静态初始化只会在首次加载 Class 对象时初始化一次。
  3. 当用 new Dog() 创建对象时,首先会在堆上为 Dog 对象分配足够的存储空间。
  4. 分配的存储空间首先会被清零,即会将 Dog 对象中的所有基本类型数据设置为默认值(数字会被置为 0,布尔型和字符型也相同),引用被置为 null。
  5. 执行所有出现在字段定义处的初始化动作。
  6. 执行构造器。你将会在”复用”这一章看到,这可能会牵涉到很多动作,尤其当涉及继承的时候。

:静态初始化只有在使用到对应的类时(在必要时),才会初始化,如果没有用到,则不会初始化

数组初始化

数组并非基本类型,获取的只是它的一个引用(已分配空间),但是还没有给数组对象本身分配空间,那么就需要初始化数组。

对象的重载

重载本质就是让相同的方法表达不同的意思。Java不能通过一个方法就能表达出所有的意思,但是冗余很多方法就显得很不合理,那么,使用重载就是最佳的解决方案。尤其是构造器的重载。
每个重载的方法都有独一无二的参数列表,这是区分重载方法的关键。
如果是基本类型作为参数的方法的重载,如果传入的基本类型大于参数类型,那么必须要进行向下转型,不然就会报错。


垃圾清理

垃圾清理,顾名思义,就是需要我们将内存中不需要的对象的空间进行释放。
垃圾回收器只知道如何释放用 new 创建的对象的内存,那么,不是通过new来创建的,那么应该怎么清理?为了处理这种情况,出现了finalize()方法。

finalize方法

finalize的作用

通过某种创建对象方式之外的方式为对象分配了存储空间,可以使用finalize来释放其内存,但是,Java中并不存在这种情况。所以,这个情况只有在使用本地方法的发送
本地方法:一种用 Java 语言调用非Java语言代码的形式,目前只支持C/C++

finalize的流程

  1. 对象在初始化的过程中会判断是否重写了finalize,方法是判断两个字段标志has_finalizer_flag和RegisterFinalizersAtInit。
  2. 如果重写了finalize,那就把当前对象注册到FinalizerThread的ReferenceQueue队列中。注册之后的对象就叫做Finalizer。方法是调用register_finalizer函数。此时java虚拟机一看当前有这个对象的引用,于是就不进行垃圾回收了。
  3. 对象开始被调用,FinalizerThread线程负责从ReferenceQueue队列中获取Finalizer对象。开始执行finalize方法,在执行之前,这个对象一直在堆中。
  4. 对象执行完毕之后,将这个Finalizer对象从队列中移除,java虚拟机一看对象没有引用了,就进行垃圾回收了。

finalize的问题

  • 并不能保证垃圾会被清理
  • 如果需要清理的对象过多,内存消耗就十分庞大。也就是在第三步时,这个对象含有finalize,进入了队列但一直没有被调用的这段时间,会一直占用内存

Java虚拟机垃圾清理

自适应模式