Java编程思想之初始化与清理

来源:互联网 发布:数据分析与知识发现 编辑:程序博客网 时间:2024/06/05 10:54

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


1 用构造器确保初始化

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

  构造器采用与类相同的名称。

  例如:

        new Rock();    // new表达式返回了对新建对象的引用

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

  在Java中,“初始化”和“创建”捆绑在一起,两者不能分离。

2 方法重载

  构造器是强制重载方法名的一个原因。因为你可能会想用多种方式创建一个对象。

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

   每个重载的方法都必须有一个独一无二的参数类型列表。

  ①涉及基本类型的重载

        由于 基本类型能从一个“较小”的类型自动提升至一个“较大”的类型,涉及重载时,可能会造成一些混淆。

        如果传入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际数据类型就会提升。

              char  byte short  int  long float double

              优先匹配刚好对应得形式参数类型,如果没有则扩大,然后匹配。(优先与它最近的数据类型匹配)

               char型略有不同,如果无法找到恰好接受char参数的方法,就会把char直接提升至int型。

               如果传入的实际参数的数据类型“较大”,就得通过类型转换来执行窄化转换。如果不这样做,编译器就会报错。

   ②在构造器中调用构造器

        在构造器中,如果为this添加了参数列表,这将产生对符合此参数列表的某个构造器的明确调用。

        尽管可以用this调用构造器,但却不能调用两个。此外,必须将构造器调用置于最起始处,否则编译器会报错。

        除构造器之外,编译器禁止在其他任何方法中调用构造器。

   ③static的含义

         static方法就是没有this的方法,在static方法的内部不能调用非静态方法。因为它没有把“所操作对象的引用”作为参数传递给当前方法。所以在内部就不能通过this关键字      调用“调用方法的那个对象”的引用。

          可以通过传递对象的引用到静态方法里,这就就可以调用非静态方法和访问非静态数据成员了。通常要达到这样的效果,只需要写一个非静态方法即可。我猜测是返回一个当前对象的引用,作为参数传递到静态方法了。

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

     Java有垃圾回收器负责回收那些无用对象占据的内存资源。但也有特殊情况,假定你的对象(并非使用new)获得了一块“特殊”的存储区域,由于垃圾回收器只知道回收那些经由new分配的内存,所以它不知道该如何释放该对象的这块”特殊“内存。

     为了应对这种情况,Java允许在类中定义一个名为finalize()的方法。它的工作原理“假定”是这样:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

   可finalize方法并没有它看起来这么有用。因为只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。如果程序执行结束,并且垃圾回收器一直都没有释放你创建的任何对象的存储空间,则随着程序的退出,那些资源也全部交还给操作系统。

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

       finalize()可以用来做对象终结条件的验证。

       例如:

        

public class FinalizeValidate{private boolean check = false;public FinalizeValidate(boolean check){this.check = check;}void checkIn(){check = false;}protected void finalize(){if(check)//当对象被终结时,check必须为false,否则会提示(作为对象终结条件的验证)System.out.println("Error:check");}}class TerminationCondition{public static void main(String[] args){FinalizeValidate fv = new FinalizeValidate(true);fv.checkIn();//正确操作new FinalizeValidate(true);//未执行上一步正确操作;System.gc();}}/*执行结果:Error:check*/

4 构造器初始化

  无法阻止自动初始化的进行,它将在构造器被调用之前发生。

   在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布在方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。

   ①静态数据初始化

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

        只有在第一个对象呗创建或者第一次访问静态数据的时候,它们才会被初始化,此后,不会再被初始化。

        初始化的顺序是先静态对象(如果它们尚未因前面的对象创建过程而被初始化),而后是“非静态”对象。


    ②对象创建的过程(假设有个名为Dog.class的类)

          1,即使没有显示地使用static关键字,构造器实际上也是静态方法。因此,当首先创建类型为Dog的对象时,或者Dog类的静态方法/静态域首次被访问时,

        Java解释器必须查找类路径,以定位Dog.class文件。

          2,然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。

          3,当用new Dog() 创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。

          4, 这块存储空间会被清零,这就自动地将Dog对象中的所有基本数据类型都设置成了默认值,而引用则被设置成了null。

          5,执行所有出现于字段定义处的初始化动作。

          6,执行构造器。











 

原创粉丝点击