Think in java学习笔记-第4章 初始化和清除

来源:互联网 发布:电子网络发票怎么下载 编辑:程序博客网 时间:2024/03/29 20:33

初始化和清除

随着计算机的进步,不安全的程序设计已成为造成编程代价高昂的罪魁祸首之一,初始化和清除是这些安全问题的其中两个。

 

一、构造方法(constructor)

如果类有构造函数,那么JAVA会在对象刚刚创建,用户还来不及使用的时候,自动调用那个类的构造函数初始化这个将要被使用的对象。

1、  构造方法的名字必须与类名完全相同!首字母不小写。

原因:

ü         使用其他名字可能与类中的成员方法的名字冲突。

ü         告诉编译器那个是构造方法,保证在对象初始化期间自动调用构造方法。

例:SimpleConstructor.java

2、  构造方法可以使用自变量,一个类可以有多个不同的构造方法。这样我们就可以选择我们创建对象的方式。

例:SimpleConstructor.java

3、  对象的创建和初始化是同一个概念,不能要这个不要那个。

4、  没有自变量的构造方法称作默认构造方法 一旦显式定义了构造方法,则系统不再提供默认构造方法。

例:DefaultConstructor.java

5、  子类继承父类所有的成员方法,但不继承父类的构造方法

6、  构造方法没有返回值。这与void返回值存在着明显的区别。New表达式会返回新建这个对象的句柄(reference)。

二、方法重载

1、  方法名相同,自变量列表不同

2、  方法重载可应用于构造方法,亦可应用于其他任何方法。

例:Overloading.java

3、  区分重载方法:必须采取独一无二的自变量类型列表;不用自变量的顺序来区分两个方法;不能根据返回值类型来区分过载的方法。

例:OverloadingOrder.java

4、  基本类型的过载:

实参类型小于形参类型:实参类型就会自动转换为形参类型处理。常数和char转换为int,

实参类型大于形参类型:必须把实参类型强制转化为形参类型,否则会报错。

例:PrimitiveOverloading.javaDemotion.java

三、this关键字

1、  引入

A和类B有相同的方法f()。内部的调用过程:

class Banana { void f(int i) { /* ... */ } }
Banana a = new Banana(), b = new Banana();
a.f(1);
b.f(2);

实际上是:

Banana.f(a,1);
Banana.f(b,2);

2、  this关键字代表当前对象的一个引用。

3、  在构造方法里调用其他构造方法时必须用this(自变量列表或空)。且只能调用一个,必须放在方法开始一行。例:Flower.java

4、  return this;返回当前对象的引用。例:Leaf.java

5、  方法自变量的名字与类成员变量的名字相同时,用this. 变量名来表示成员变量。

四、static的含义

1、  什么时候用static(静态)关键字

1)     一种情形是只想用一个存储区域来保存一个特定的数据——无论要创建多少个对象,甚至根本不创建对象。

2)     另一种情形是我们需要一个特殊的方法,它没有与这个类的任何对象关联。也就是说,即使没有创建对象,也需要一个能调用的方法。

2、  static的含义

1)     它意味着一个特定的方法没有this

2)     我们不可从一个static方法内部发出对非static方法的调用

3)     而且在没有任何对象的前提下,我们可针对类本身发出对一个static方法的调用。

4)     一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一起。

5)     为了将数据成员或方法设为static,只需在定义前置和这个关键字即可。例如,下述代码能生成一个static数据成员,并对其初始化:
class Static Test {
Static int i = 47;
}
现在,尽管我们制作了两个StaticTest对象,但它们仍然只占据StaticTest.i的一个存储空间。这两个对象都共享同样的i

6)     有两个办法可引用一个static变量。正如上面展示的那样,可通过一个对象命名它,如st2.i。亦可直接用它的类名引用,(最好用这个办法引用static变量,因为它强调了那个变量的静态本质)

五、清除:收尾和垃圾收集

1、  垃圾收集的原理

1)     垃圾收集器只知道释放那些由new分配的内存

2)     在理想情况下,它的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存。

3)     垃圾收集并不等于破坏 Java对象并非肯定能作为垃圾被收集去。垃圾收集不等于清除,当我们不需要一个对象之前,必须创建一个原始的方法,用它来进行这种清除。我们的对象可能不会当作垃圾被收掉!有时可能发现一个对象的存储空间永远都不会释放,因为自己的程序永远都接近于用光空间的临界点。若程序执行结束,而且垃圾收集器一直都没有释放我们创建的任何对象的存储空间,则随着程序的退出,那些资源会返回给操作系统。这是一件好事情,因为垃圾收集本身也要消耗一些开销。如永远都不用它,那么永远也不用支出这部分开销。

2、  为什么要用finalize()?

1)       垃圾收集只跟内存有关!垃圾收集器存在的唯一原因是为了回收程序不再使用的内存。自己写的finalize()方法,也必须同内存以及内存释放有关。不论对象以什么方式创建,内存都是由垃圾回收器负责的。不必过多地使用finalize()finalize()最有用处的地方之一是观察垃圾收集的过程。例:Garbage.java

3、  若希望执行除释放存储空间之外的其他某种形式的清除工作,仍然必须调用Java中的一个方法。它等价于C++的破坏器,只是没后者方便。

4、  为强制进行收尾工作,可先调用System.gc(),再调用System.runFinalization()。这样可清除到目前为止没有使用的所有对象。

六、类成员变量的初始化

1、  默认初始化:一个类的数据成员都会保证获得一个初始值。

例:InitialValues.java

2、  规定初始化

1)     定义变量的同时也为其赋值

2)     可通过调用一个方法来提供初始值:这个方法亦可使用自变量,但那些自变量不可是尚未初始化的其他类成员。

3、  在构造方法内部初始化:先执行默认初始化。

4、  成员变量的初始化顺序

1)     在一个类里,初始化的顺序是由变量在类内的定义顺序决定的。

例:OrderOfInitialization.java

2)     成员变量在调用任何方法(包括构造方法)之前得到初始化。

5、  静态数据的初始化

1)     static初始化只有在必要的时候才会进行。只被初始化一次。

2)     初始化的顺序是首先static(如果它们尚未由前一次对象创建过程初始化),接着是非static对象。

例:StaticInitialization.java

3)     对象的创建过程。请考虑一个名为Dog的类:

ü           Java解释器找到Dog.class(在事先设好的类路径里搜索)。

ü           找到Dog.class后(它会创建一个Class对象),它的所有static初始化模块都会运行。因此,static初始化仅发生一次——Class对象首次载入的时候。

ü           创建一个new Dog()时,Dog对象的构建进程首先会在内存堆(Heap)里为一个Dog对象分配足够多的存储空间。

ü           这种存储空间会清为零,将Dog中的所有基本类型设为它们的默认值

ü           进行字段定义时发生的所有初始化都会执行。

ü           执行构建器。

6、  静态块

例:ExplicitStatic.java

7、  非静态块

例:Mugs.java

七、数组初始化

1、  数组的定义:type[] name;type name[]

2、  编译器不允许我们告诉它一个数组有多大。我们拥有的一切就是指向数组的一个句柄,而且尚未给数组分配任何空间。为了给数组创建相应的存储空间,必须编写一个初始化表达式。

3、  对于数组,初始化工作可在代码的任何地方出现,但也可以使用一种特殊的初始化表达式,它必须在数组创建的地方出现。这种特殊的初始化是一系列由花括号封闭起来的值。存储空间的分配(等价于使用new)将由编译器在这种情况下进行。例如:
int[] a1 = { 1, 2, 3, 4, 5 };
那么为什么还要定义一个没有数组的数组句柄呢?
int[] a2;
事实上在Java中,可将一个数组分配给另一个,所以能使用下述语句:
a2 = a1;

4、  这里也出现了一些新东西:所有数组都有一个本质成员(无论它们是对象数组还是基本类型数组),可对其进行查询——但不是改变,从而获知数组内包含了多少个元素。这个成员就是length。由于Java数组从元素0开始计数,所以能索引的最大元素编号是“length-1”。一旦超过边界,就生成一个运行期错误(即一个违例,这是第9章的主题)。

5、  程序编写期间,如果不知道在自己的数组里需要多少元素,那么又该怎么办呢?此时,只需简单地用new在数组里创建元素。在这里,即使准备创建的是一个基本数据类型的数组,new也能正常地工作(new不会创建非数组的基本类型):

例:ArrayNew.java

6、  若操作的是一个非基本类型对象的数组,那么无论如何都要使用new

例:ArrayClassObj.java

7、  多维数组

例:MultiDimArray.java

 

 
原创粉丝点击