`
m_tou
  • 浏览: 30286 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

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

阅读更多

初始化和清除

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

 

一、 构造方法 (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.java





Demotion.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

 

2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics