第5章 初始化与清理

5.2 方法重载

Java的方法重载与C++一样,不能以返回值作为两个函数重载的区别。

另外,后面的章节中会有介绍,Java存在一个叫做协变返回类型的:子类中的一个覆盖方法可以返回基类被覆盖方法返回值的子类。

5.4 this关键字

Java中this关键字同样代表正在调用方法的对象本身,是编译器为每个非static方法传递的第一个参数(隐藏传递,程序员感觉不到,与Java,C++这种隐藏传递相对的是,Python要求明确方法的第一个参数为self,也就是对象自己的引用。)

Java中的this有一个更重要的用途,在构造函数里调用重载的其他构造函数。C++中,一个构造函数不可以调用另外一个构造函数,因为在C++中构造函数有着初始化vtable的作用,重复构造vtable是不允许的。

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

关于finalize()方法有关的要牢记的三点:

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

关于第三点有必要引用书上的原话:“也就是说,使用垃圾回收器的唯一原因是为了回收程序不再使用的内存。所以对于与垃圾回收有关的任何行为来说(尤其是finalize()方法),它们也必须同内存及其回收有关。但这是否意味着要是对象中含有其他对象,finalize()就应该明确释放那些对象呢?不,无论对象是如何创建的,垃圾回收器都会负责释放对象占据的内存。这就将finalize()的需求限制到一种特殊情况,即通过某种创建对象以外的方式为对象分配了存储空间。”-- 本地方法分配的内存需要在finalize()中释放,比如对象的某个域由C的malloc来分配内存,这时候需要在finalize()中调用相应的free方法类释放内存。

5.5.3 终结条件

作为finalize()方法的一种使用技巧,通过GC动作检查你的程序是否正确,比如书中的这个列子,所有的Book对象在程序结束的时候(或者说对象不再使用的时候)都应该是回到图书馆的。

import static java.lang.System.out;
class Book {
  boolean checkedOut = false;
  Book(boolean checkOut) {
    checkedOut = checkOut;
  }
  void checkIn() {
    checkedOut = false;
  }
  protected void finalize() {
    if(checkedOut)
      out.println("Error: checked out");
    // Normally, you'll also do this
    // super.finalize(); // Call the base class version
  }
}
 
public class TerminationCondition {
  public static void main(String args[]){
    Book novel = new Book(true);
    // Proper cleanup:
    novel.checkIn();
    // Drop the reference. forgot to cleanup
    new Book(true);
    // Force garbage collection & finalization
    System.gc();    
  }
} /*Output:
Error: checked out
*/

5.6 成员初始化

类的每一个Primitive数据成员都会获得一个初始值(0,NULL or False)。

指定初始化,也可以用函数,但这个函数如果有参数的话,那参数必须同样被初始化。

5.7 构造器初始化

import static java.lang.System.out;

class Dog {
  public Dog(String name) {
    out.println(name + " constructor");
  }
}
public class HelloWorld{
  private static Dog Dog1 = new Dog("Dog1");
  private Dog dog2 = new Dog("Dog2");
  private Dog dog3;
  private Dog dog4 = new Dog("Dog4");
  private static Dog dog5;
  private Dog dog6 = new Dog("Dog6");
  
  public static void main(String []args){
    new HelloWorld();
    out.println("----");
    new HelloWorld();
  }
  
  {
    dog3 = new Dog("Dog3");
  }
  
  static {
    dog5 = new Dog("Dog5");
  }
  
  public HelloWorld(){
    dog6 = new Dog("Dog6");
  }
} 

总结一下对象的创建过程:

  1. 及时没有显示地使用static关键字,构造器实际上也是静态方法。因此当首次创建类型为Dog的对象时,或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。
  2. 然后加载Dog.class(后面会学到,这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
  3. 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
  4. 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(0,False&Null)。
  5. 执行所有出现于字段定义出的初始化动作。
  6. 执行构造器。

5.8 数组的初始化

基本数据类型的数组是一组包含了基本类型数据的数组,自动被初始化为"空";对象的数组是一组包含了引用的数组,每个元素都是一个空引用,如果没有赋值。

 1 import static java.lang.System.out;
 2 public class HelloWorld{
 3   public static void main(String []args){
 4     int arr1[] = new int[2];
 5     for(int item : arr1)
 6       out.println(item);
 7     out.println("----");
 8     Integer arr2[] = new Integer[2];
 9     for(Integer item : arr2)
10       out.println(item);
11     out.println("----");
12     arr2[0] = new Integer(0);
13     arr2[1] = new Integer(1);
14     for(Integer item : arr2)
15       out.println(item);    
16   }
17 }/*Output
18 0
19 0
20 ----
21 null
22 null
23 ----
24 0
25 1
26 */
27    

 

 

posted on 2013-05-02 09:59  peter9606  阅读(160)  评论(0编辑  收藏  举报

导航