Java 初始化与清理

来源:互联网 发布:网络销售是正规工作么 编辑:程序博客网 时间:2024/05/21 10:00

初始化和清理(cleanup)正是涉及安全的两个问题。

C++引入了构造器(constructor)的概念,这是一个在创建对象时被自动调用的特殊方法。

Java中采用了构造器,并额外提供了“垃圾回收器”。对于不再使用的内存资源,垃圾回收器能自动将其释放。

1 用构造器确保初始化

在Java中,通过提供构造器,类的设计者可能确保每个对象都会得到初始化。创建对象时,如果其类具有构造器,Java就会在用户有能力操作对象之前自动调用相应的构造器,从而保证了初始化的进行。

接下来的问题就是如何命名这个方法。有两个问题:
第一,所取的任何名字都可能与类的某个成员名称相冲突;
第二,调用构造器是编译器的责任,所以必须让编译器知道应该调用哪个方法。

C++语言中采用的解决方案看来最简单且更符合逻辑,所以在Java中也采用了这种方案:即构造器采用与类相同的名称。

现在,在创建对象时:

new Dog();

将会为对象分配存储空间,并调用相应的构造器。

由于构造器的名称必须与类名完全相同。

不接受任何参数的构造器叫做默认构造器,Java文档中通常使用术语无参构造器。

构造器是一种特殊类型的方法,因为它没有返回值。

2 方法重载

所谓方法则是给某个动作取的名字。

名字起得好可以使系统更易于理解和修改。让读者易于理解。

将人类语言中存在细微差别的概念“映射”到程序设计语言中时,问题随之而生。

在Java(和C++)里,构造器是强制重载方法名的另一个原因。

既然构造器的名字已经由类名所决定,就只能有一个构造器名。

一个默认构造器,另一个取字符串作为形式参数。

为了让方法名称相同而形式参数不同的构造器同时存在,必须用到方法重载。

3 默认构造器

默认构造器(“无参构造器”)是没有形式参数的—它的作用是创建一个“默认对象”。如果你写的类中没有构造器,则编译器会自动帮你创建一个默认构造器。

如果已经定义了一个构造器(无论是否有参数),编译器就不会帮你自动创建默认构造器。

4 this关键字

假设你希望在方法的内部获得对当前对象的引用。

this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。this的用法和其他对象引用并无不同。

static方法就是没有this的方法。在static方法的内部不能调用非静态方法,反过来倒是可以的。

而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。它很像全局方法。Java中禁止使用全局方法,但你在类中置入static方法就可以访问其他static方法和static域。

5 清理:终结处理和垃圾回收

C++中,对象一定会被销毁(如果程序中没有缺陷的话)

而Java里的对象却并非总是被垃圾回收。或者换句话说:

  1. 对象可能不被垃圾回收。
  2. 垃圾回收并不等于“析构”。
  3. 垃圾回收只与内存有关。

可以简单地认为,正是由于垃圾回收的机制存在,使得Java没有析构函数。

记住,无论是“垃圾回收”还是“终结”,都不保证一定会发生。如果Java虚拟机(JVM)并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的。

垃圾回收如何工作

引用记数是一种简单但速度很慢的垃圾回收技术。

如果对象之间存在循环引用,可能会出现“对象应该被回收,但是引用计数却不为零”的情况。

在一些更快的垃圾回收模式中,垃圾回收器并非基于引用记数技术。它们依据的思想是:对任何“活”的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用。这条引用链条可能会穿过数个对象层次。由此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有“活”的对象。

在这种方式下,Java虚拟机将采用一种自适应的垃圾回收技术。至于如何处理找到的存活对象,取决于不同的Java虚拟机实现。

有一种做法叫做 停止-复制(stop-and-copy)。显然这意味着,先暂停程序的运行(所以它不属于后台回收模式),然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。

“标记-清扫”所依据的思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。

“停止-复制”的意思是这种垃圾回收动作不是在后台进行的;相反,垃圾回收动作发生的同时,程序将会被暂停。

6 成员初始化

7 构造器初始化

静态数据的初始化

无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量。因此它只能作用于域。

如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初值;如果它是一个对象引用,那么它的默认初始化值就是null。

8 数组初始化

数组只是相同类型的、同一个标识符名称封装到一起的一个对象序列或基本类型数据序列。

数组是通过方括号下标操作符[]来定义和使用的。

可变参数列表

第二种形式提供了一种方便的语法来创建对象并调用方法,以获得与C的可变参数列表(C通常把它简称为varargs)一样的效果。

这可以应用于参数个数或类型未知的场合。

Java SE5之前:

static void printArray(Object[] args) {    for(Object obj:args){        System.out.print(obj + " ");    }    System.out.println();}

Java SE5之后:可以产生可变的参数列表。

static void printArray(Object... args) {    for(Object obj:args){        System.out.print(obj + " ");    }    System.out.println();}

9 枚举类型

Java SE5中添加了enum关键字,它使得我们在需要群组并使用枚举类型集时,可以很方便地处理。

由于枚举类型的实例是常量,因此按照命名惯例它们都用大写字母表示(如果在一个名称中有多个单词,用下划线将它们隔开)。

0 0
原创粉丝点击