java编程思想(读书笔记):4.初始化和清理

时间:2023-02-22 19:38:28

四、初始化和清理

初始化和清理时众多安全议题中的两个。

区分重载函数:每个重载函数都需要具备独一无二的引数列。

关键字this,编译器暗自做手脚,将调用者的reference传入到对象方法中来取代this。这个关键字仅用于函数之内,能取得“唤起此一函数”的那个object reference。

关于构造函数中this的用法:虽然能够由this调用一个构造函数,却不能以相同方法调用两个或更多。此外,对另一构造函数的调用必须是在最起始位置,否则编译器会报错。同时,编译器不允许在构造函数之外的任何函数内调用构造函数。

清理:关于终结(finalization)和回收(gc):假设你的对象并非由new获得某种“特殊”内存。垃圾回收器只知道释放那些经由new分配出来的内存,因此它并不知道如何释放你这个对象占用的“特殊”内存。为了回应这种情况,java提供一个finalize()函数,你可以为自己的class定义这一函数。                                                                     

关于垃圾回收器(gc):

1.      垃圾回收不等于解构

2.      你的对象可能不会被回收,正是因为这样,所以在finalize()中完成你必要的清理动作不合适。所以不应该使用finalize()做一般用途的清理工作。

3.      垃圾回收动作只回收内存。垃圾回收器存在的唯一理由,就是要回收那些在你程序中再也用不着的内存空间。似乎只有在你通过java的非正常管道来分配内存,打算做一些类似C会做的事情时,才是使用finalize()的适当时机。

4.      无论是垃圾回收动作或者是终结动作,都不保证一定能发生。如果java虚拟机(JVM)并未面临内存耗尽的情境,它不会浪费时间与垃圾回收上。

初始化:你无法杜绝发生于构造函数执行之前的自动初始化动作。

初始化次序:class中的初始化次序取决于变量中class中定义次序。变量定义可以散落在各处,而且有可能介于各个函数定义之间,但所有变量一定会在任何一个函数(甚至是构造函数)被调用之前完成初始化。Static的初始化动作只在必要时刻才会发生,如果你没有产生Table对象,也没有调用Table.b1或b2等static变量,那么static变量就永远不会被产生。如果static变量并未因为早先的对象生成过程而被初始化,那么初始化次序会以static为优先,然后才是non-static对象。

对象生成过程摘要:

1.      当某个型别为Dog的对象首次被产生出来,或者是当class Dog的static函数或static数据成员被首次调用时,java直译器必须查找环境变量classpath所指定的位置,找出Dog.class。

2.      一旦Dog.class被装载(这样就产生一个class对象)。它的所有static初始动作会被执行起来,因此static初始化动作仅会发生一次,就是class对象被首次装载时。

3.      当new Dog()时,建构过程会先为Dog对象在heap上分配足够的存储空间。

4.      这块存储空间会先被清零,并自动将Dog对象内所有属于基本型别的数据设为缺省值,并将reference设为null.

5.      执行所有的数据定义处的初始化动作。

6.      执行构造函数。这中间将牵扯极多动作,尤其是当继承关系卷入时。

Array的初始化:当定义一个array,“int[] a;”。上述编译器并不允许告诉他array有多大。此刻你所拥有的,只是一个reference,代表某个array,但是并没有对应的空间。如果想为该array产生必要的存储空间,必须撰写初始化表达式。Array的生成发生在执行期。

“Integer[] a = new Integer[20];”以new产生array之后,这还是个referencearray。只有在“生成新的integer对象以初始化reference”之后,初始化动作才算完成,即”a[i] = new Integer(50);”。如果忘记生成对象,当你企图读取空的array位置时,会获得一个异常。

多维数组:array之中形成整个矩阵的那些向量可以是任意长度的。(举例,二维矩阵不一定是矩形,可以是三角形等)。对于基本类型,没有明确给定array的元素值的话,它们会被自动初始化为0或false。对于非基本型别,它们会被初始化为null。